You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@mesos.apache.org by "Jojy Varghese (JIRA)" <ji...@apache.org> on 2015/09/17 16:30:06 UTC
[jira] [Updated] (MESOS-3455) Higher level construct for expressing
process dispatch
[ https://issues.apache.org/jira/browse/MESOS-3455?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Jojy Varghese updated MESOS-3455:
---------------------------------
Description:
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:
class Interface
{
virtual Future<size_t> writeToFile(const char* data) = 0;
virtual ~Interface();
};
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:
// -- hpp file
class InterfaceProcess;
class InterfaceImpl : public Interface
{
public:
Try<Owned<InterfaceImpl>> create(const Flags& flags);
virtual Future<size_t> writeToFile(const char* data);
~InterfaceImpl();
private:
Owned<InterfaceProcess> process;
};
// -- cpp file
Try<Owned<InterfaceImpl>> create(const Flags& flags)
{
// Code to create the InterfaceProcess class.
}
Future Future<size_t> InterfaceImpl::writeToFile(const char* data)
{
process->dispatch(
&InterfaceProcess::writeToFile,
data);
}
InterfaceImpl::InterfaceImpl()
{
// Code to spawn the process
}
InterfaceImpl::~InterfaceImpl()
{
// Code to stop the process.
}
At the caller/client site, the code would look like:
Try<Owned<Interface>> in = InterfaceImpl::create(flags);
Future<size_t> result =
in->writeToFile(data);
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:
ProcessDispatcher<Interface, InterfaceImplmentation>
DispatchInterface
Any interface that provides an implementation that can be "dispatched" can be
expressed using this component.
This component can be expressed as:
Dispatchable<Interface>
Usage:
Simple usage
Try<Owned<Dispatchable<Interface>>> dispatcher =
ProcessDispatcher<Interface, InterfaceImpl>::create(flags);
Future<size_t> result =
dispatcher->dispatch(
Interface::writeToFile,
data);
Collecting the interface in a container
vector<Owned<Dispatchable<Interface>>> dispatchCollection;
Try<Owned<Dispatchable<Interface>>> dispatcher1 =
ProcessDispatcher<Interface, InterfaceImpl1>::create(flags);
Try<Owned<Dispatchable<Interface>>> dispatcher2 =
ProcessDispatcher<Interface, InterfaceImpl2>::create("test");
dispatchCollection.push_back(dispatcher1);
dispatchCollection.push_back(dispatcher2);
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.
Less code in the text segment.
was:
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:
class Interface
{
virtual Future<size_t> writeToFile(const char* data) = 0;
virtual ~Interface();
};
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:
// -- hpp file
class InterfaceProcess;
class InterfaceImpl : public Interface
{
public:
Try<Owned<InterfaceImpl>> create(const Flags& flags);
virtual Future<size_t> writeToFile(const char* data);
~InterfaceImpl();
private:
Owned<InterfaceProcess> process;
};
// -- cpp file
Try<Owned<InterfaceImpl>> create(const Flags& flags)
{
// Code to create the InterfaceProcess class.
}
Future Future<size_t> InterfaceImpl::writeToFile(const char* data)
{
process->dispatch(
&InterfaceProcess::writeToFile,
data);
}
InterfaceImpl::InterfaceImpl()
{
// Code to spawn the process
}
InterfaceImpl::~InterfaceImpl()
{
// Code to stop the process.
}
At the caller/client site, the code would look like:
Try<Owned<Interface>> in = InterfaceImpl::create(flags);
Future<size_t> result =
in->writeToFile(data);
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:
ProcessDispatcher<Interface, InterfaceImplmentation>
DispatchInterface
Any interface that provides an implementation that can be "dispatched" can be
expressed using this component.
This component can be expressed as:
Dispatchable<Interface>
Usage:
Simple usage
Try<Owned<Dispatchable<Interface>>> dispatcher =
ProcessDispatcher<Interface, InterfaceImpl>::create(flags);
Future<size_t> result =
dispatcher->dispatch(
Interface::writeToFile,
data);
Collecting the interface in a container
vector<Owned<Dispatchable<Interface>>> dispatchCollection;
Try<Owned<Dispatchable<Interface>>> dispatcher1 =
ProcessDispatcher<Interface, InterfaceImpl1>::create(flags);
Try<Owned<Dispatchable<Interface>>> dispatcher2 =
ProcessDispatcher<Interface, InterfaceImpl2>::create("test");
dispatchCollection.push_back(dispatcher1);
dispatchCollection.push_back(dispatcher2);
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.
Less code in the text segment.
> Higher level construct for expressing process dispatch
> ------------------------------------------------------
>
> Key: MESOS-3455
> URL: https://issues.apache.org/jira/browse/MESOS-3455
> Project: Mesos
> Issue Type: Bug
> Components: libprocess
> Reporter: Jojy Varghese
> Assignee: Jojy Varghese
>
> 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:
> class Interface
> {
> virtual Future<size_t> writeToFile(const char* data) = 0;
> virtual ~Interface();
> };
> 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:
> // -- hpp file
> class InterfaceProcess;
> class InterfaceImpl : public Interface
> {
> public:
> Try<Owned<InterfaceImpl>> create(const Flags& flags);
> virtual Future<size_t> writeToFile(const char* data);
> ~InterfaceImpl();
> private:
> Owned<InterfaceProcess> process;
> };
> // -- cpp file
> Try<Owned<InterfaceImpl>> create(const Flags& flags)
> {
> // Code to create the InterfaceProcess class.
> }
> Future Future<size_t> InterfaceImpl::writeToFile(const char* data)
> {
> process->dispatch(
> &InterfaceProcess::writeToFile,
> data);
> }
> InterfaceImpl::InterfaceImpl()
> {
> // Code to spawn the process
> }
> InterfaceImpl::~InterfaceImpl()
> {
> // Code to stop the process.
> }
> At the caller/client site, the code would look like:
> Try<Owned<Interface>> in = InterfaceImpl::create(flags);
> Future<size_t> result =
> in->writeToFile(data);
> 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:
> ProcessDispatcher<Interface, InterfaceImplmentation>
> DispatchInterface
> Any interface that provides an implementation that can be "dispatched" can be
> expressed using this component.
> This component can be expressed as:
> Dispatchable<Interface>
> Usage:
> Simple usage
> Try<Owned<Dispatchable<Interface>>> dispatcher =
> ProcessDispatcher<Interface, InterfaceImpl>::create(flags);
> Future<size_t> result =
> dispatcher->dispatch(
> Interface::writeToFile,
> data);
> Collecting the interface in a container
> vector<Owned<Dispatchable<Interface>>> dispatchCollection;
> Try<Owned<Dispatchable<Interface>>> dispatcher1 =
> ProcessDispatcher<Interface, InterfaceImpl1>::create(flags);
> Try<Owned<Dispatchable<Interface>>> dispatcher2 =
> ProcessDispatcher<Interface, InterfaceImpl2>::create("test");
> dispatchCollection.push_back(dispatcher1);
> dispatchCollection.push_back(dispatcher2);
> 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.
> Less code in the text segment.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)