Project: mesos
Issue MESOS-3455: Higher level construct for expressing process dispatch
Since mesos code is based on the actor model and dispatching an interface asynchronously is a large part of the code base, generalizing the concept of asynchronously dispatching an interface would eliminate the need to manual programming of the dispatch boilerplate. An example usage: For a simple interface like: {code} class Interface { virtual Future writeToFile(const char* data) = 0; virtual ~Interface(); }; {code} Today the developer has to do the following: a. Write a wrapper class that implements the same interface to add the dispatching boilerplate. b. Spend precious time in reviews. c. Risk introducing bugs. None of the above steps add any value to the executable binary. The wrapper class would look like: {code} // -- hpp file class InterfaceProcess; class InterfaceImpl : public Interface { public: Try> create(const Flags& flags); virtual Future writeToFile(const char* data); ~InterfaceImpl(); private: Owned process; }; // -- cpp file Try> create(const Flags& flags) { // Code to create the InterfaceProcess class. } Future Future InterfaceImpl::writeToFile(const char* data) { process->dispatch( &InterfaceProcess::writeToFile, data); } InterfaceImpl::InterfaceImpl() { // Code to spawn the process } InterfaceImpl::~InterfaceImpl() { // Code to stop the process. } {code} At the caller/client site, the code would look like: {code} Try> in = InterfaceImpl::create(flags); Future result = in->writeToFile(data); {code} Proposal We should use C++'s rich language semnatics to express the intent and avoid the boilerplate we write manually. The basic intent of the code that leads to all the boilerplate above is: a. An interface that provides a set of functionality. b. An implementation of the interface. c. Ability to dispatch that interface asynchronously using actor. C++ has a rich set of generics that can be used to express above. Components ProcessDispatcher This component will "dispatch" an interface implementation asychronously using the process framework. This component can be expressed as: {code} ProcessDispatcher {code} DispatchInterface Any interface that provides an implementation that can be "dispatched" can be expressed using this component. This component can be expressed as: {code} Dispatchable {code} Usage: Simple usage {code} Try>> dispatcher = ProcessDispatcher::create(flags); Future result = dispatcher->dispatch( Interface::writeToFile, data); {code} Collecting the interface in a container {code} vector>> dispatchCollection; Try>> dispatcher1 = ProcessDispatcher::create(flags); Try>> dispatcher2 = ProcessDispatcher::create("test"); dispatchCollection.push_back(dispatcher1); dispatchCollection.push_back(dispatcher2); {code} The advantages of using the generic dispatcher: Saves time by avoiding to write all the boilerplate and going through review cycles. Less bugs. Focus on real problem and not boilerplate.
Story points: 6