{"action":"created","issue":{"url":"https://api.github.com/repos/apache/mesos/issues/65","labels_url":"https://api.github.com/repos/apache/mesos/issues/65/labels{/name}","comments_url":"https://api.github.com/repos/apache/mesos/issues/65/comments","events_url":"https://api.github.com/repos/apache/mesos/issues/65/events","html_url":"https://github.com/apache/mesos/pull/65","id":106460187,"number":65,"title":"Process dispatch","user":{"login":"conqer","id":1635173,"avatar_url":"https://avatars.githubusercontent.com/u/1635173?v=3","gravatar_id":"","url":"https://api.github.com/users/conqer","html_url":"https://github.com/conqer","followers_url":"https://api.github.com/users/conqer/followers","following_url":"https://api.github.com/users/conqer/following{/other_user}","gists_url":"https://api.github.com/users/conqer/gists{/gist_id}","starred_url":"https://api.github.com/users/conqer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/conqer/subscriptions","organizations_url":"https://api.github.com/users/conqer/orgs","repos_url":"https://api.github.com/users/conqer/repos","events_url":"https://api.github.com/users/conqer/events{/privacy}","received_events_url":"https://api.github.com/users/conqer/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-09-15T01:48:28Z","updated_at":"2015-09-17T20:03:00Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/apache/mesos/pulls/65","html_url":"https://github.com/apache/mesos/pull/65","diff_url":"https://github.com/apache/mesos/pull/65.diff","patch_url":"https://github.com/apache/mesos/pull/65.patch"},"body":"Generic Asynchronous Dispatcher   \r\n------                                               \r\n                                                                                 \r\nMotivation\r\n--------                                                                \r\n  Since mesos code is based on the actor model and dispatching an interface      \r\nasynchronously is a large part of the code base, generalizing the higher level concept of     \r\nasynchronously dispatching an interface would eliminate the need to manually \r\nprogram the dispatch boilerplate.                                         \r\n                                                                                 \r\nAn example usage:                                                                                                        \r\nFor a simple interface like:                                                     \r\n\r\n```C                                                                    \r\nclass Interface                                                                  \r\n{                                                                                \r\n  virtual Future<size_t> writeToFile(const char* data) = 0;                      \r\n  virtual ~Interface();                                                          \r\n};     \r\n```                                                                     \r\n                                                                                 \r\nToday the developer has to do the following:                                     \r\n                                                                                 \r\na.  Write a wrapper class that implements the same interface to add the          \r\n    dispatching boilerplate.                                                     \r\nb.  Spend precious time in reviews.                                              \r\nc.  Risk introducing bugs.                                                       \r\n                                                                                 \r\n  None of the above steps add any value to the executable binary.                \r\n                                                                                 \r\nThe wrapper class would look like:                                               \r\n                                                                                 \r\n```C                                                \r\n                                                                                 \r\n// -- hpp file                                                                   \r\nclass InterfaceProcess;                                                          \r\n                                                                                 \r\nclass InterfaceImpl : public Interface                                           \r\n{                                                                                \r\npublic:                                                                          \r\n  Try<Owned<InterfaceImpl>> create(const Flags& flags);                          \r\n                                                                                 \r\n  virtual Future<size_t> writeToFile(const char* data);                          \r\n                                                                                 \r\n  ~InterfaceImpl();\r\nprivate:                                                                         \r\n  Owned<InterfaceProcess> process;                                               \r\n};                                                                               \r\n                                                                                 \r\n// -- cpp file                                                                   \r\nTry<Owned<InterfaceImpl>> create(const Flags& flags)                             \r\n{                                                                                \r\n  // Code to create the InterfaceProcess class.                                  \r\n}                                                                                \r\n                                                                                 \r\nFuture Future<size_t> InterfaceImpl::writeToFile(const char* data)               \r\n{                                                                                \r\n  process->dispatch(                                                             \r\n    &InterfaceProcess::writeToFile,                                              \r\n    data);                                                                       \r\n}                                                                                \r\n                                                                                 \r\nInterfaceImpl::InterfaceImpl()                                                   \r\n{                                                                                \r\n  // Code to spawn the process                                                   \r\n}                                                                                \r\n                                                                                 \r\nInterfaceImpl::~InterfaceImpl()                                                  \r\n{                                                                                \r\n  // Code to stop the process.                                                   \r\n}   \r\n```                                                                           \r\n                                                                                                                             \r\nAt the caller/client site, the code would look like:                             \r\n```C                                                                             \r\nTry<Owned<Interface>> in = InterfaceImpl::create(flags);                         \r\nFuture<size_t> result =                                                          \r\n  in->writeToFile(data);                                                                       \r\n```     \r\nProposal                                                                         \r\n---------                                                                        \r\n  We should use C++'s rich language semnatics to express the intent and avoid    \r\nthe boilerplate we write manually.                                               \r\n  The basic intent of the code that leads to all the boilerplate above is:       \r\n                                                                                 \r\na. An interface that provides a set of functionality.                            \r\nb. An implementation of the interface.                                           \r\nc. Ability to dispatch that interface asynchronously using actor.                \r\n                                                                                 \r\nC++ has a rich set of generics that can be used to express above.                \r\n                                                                                 \r\nComponents                                                                       \r\n-------                                                                          \r\n                                                                                 \r\n1. ProcessDispatcher                                                             \r\n  This component will \"dispatch\" an interface implementation asychronously using \r\nthe process framework.                                                           \r\n  This component can be expressed as:                                            \r\n                                                                                 \r\n ```C\r\n ProcessDispatcher<Interface, InterfaceImplmentation>   \r\n```                        \r\n                                                                                 \r\n2. DispatchInterface                                                             \r\n  Any interface that provides an implementation that can be \"dispatched\" can be  \r\nexpressed using this component.                                                  \r\n  This component can be expressed as:                                            \r\n                                                                                 \r\n```C  \r\nDispatchable<Interface>  \r\n```\r\n\r\nUsage:\r\n------                                                                \r\n1. Simple usage                                                                  \r\n```C                                                                                 \r\nTry<Owned<Dispatchable<Interface>>> dispatcher =                                 \r\n  ProcessDispatcher<Interface, InterfaceImpl>::create(flags);                    \r\n                                                                                 \r\nFuture<size_t> result =                                                          \r\n  dispatcher->dispatch(                                                          \r\n    Interface::writeToFile,                                                      \r\n    data);                                                                       \r\n```\r\n                                                                             \r\n2. Collecting the interface in a container                                       \r\n ```C                                                                                \r\nvector<Owned<Dispatchable<Interface>>> dispatchCollection;                       \r\n                                                                                 \r\nTry<Owned<Dispatchable<Interface>>> dispatcher1 =                                \r\n  ProcessDispatcher<Interface, InterfaceImpl1>::create(flags);                   \r\n                                                                                 \r\nTry<Owned<Dispatchable<Interface>>> dispatcher2 =                                \r\n  ProcessDispatcher<Interface, InterfaceImpl2>::create(\"test\");                  \r\n                                                                                 \r\ndispatchCollection.push_back(dispatcher1);                                       \r\ndispatchCollection.push_back(dispatcher2);    \r\n\r\n ```\r\n\r\nThe advantages of using the generic dispatcher:\r\n                                                                                                                 \r\n- Saves time by avoiding to write all the boilerplate and going through review   \r\n  cycles.                                                                        \r\n- Less bugs.                                                                     \r\n- Focus on real problem and not boilerplate.                                     \r\n- Less code to represent a primitive.                                                                               \r\n           \r\n"},"comment":{"url":"https://api.github.com/repos/apache/mesos/issues/comments/141209566","html_url":"https://github.com/apache/mesos/pull/65#issuecomment-141209566","issue_url":"https://api.github.com/repos/apache/mesos/issues/65","id":141209566,"user":{"login":"conqer","id":1635173,"avatar_url":"https://avatars.githubusercontent.com/u/1635173?v=3","gravatar_id":"","url":"https://api.github.com/users/conqer","html_url":"https://github.com/conqer","followers_url":"https://api.github.com/users/conqer/followers","following_url":"https://api.github.com/users/conqer/following{/other_user}","gists_url":"https://api.github.com/users/conqer/gists{/gist_id}","starred_url":"https://api.github.com/users/conqer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/conqer/subscriptions","organizations_url":"https://api.github.com/users/conqer/orgs","repos_url":"https://api.github.com/users/conqer/repos","events_url":"https://api.github.com/users/conqer/events{/privacy}","received_events_url":"https://api.github.com/users/conqer/received_events","type":"User","site_admin":false},"created_at":"2015-09-17T20:03:00Z","updated_at":"2015-09-17T20:03:00Z","body":"@haosdent  What do you think about the usage difference. Earlier at the call site it used to be:\r\ninterface->foo(arg1, arg2);\r\n\r\nWith this change, the interface would be:\r\ndispatcher.dispatch(&interface::foo, arg1, arg2);\r\n"}}