|
Boost : |
From: Dean Michael Berris (mikhailberis_at_[hidden])
Date: 2007-03-07 13:58:18
On 3/6/07, Frank Mori Hess <frank.hess_at_[hidden]> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Tuesday 06 March 2007 16:54 pm, Jason Turner wrote:
> > It was only after setting out to implement the project did I realize
> > that this concept had been published a few years back under the name
> > "Active Object" (http://en.wikipedia.org/wiki/Active_Object) and there
> > are a couple of similar implementations floating around.
>
> I've written a little active object framework too. In fact, it was what I
> was working on which led to me getting quite sidetracked on thread-safe
> signals. But now that I'm wrapping that up, I should be able to release
> my code soon. It works, I just haven't released it because I haven't
> written any documentation yet. I basically just combined ideas from the
> active object paper by Lavender, et. al., the ACE implementation, and
> boost, and added some syntactic sugar. I didn't try to provide a full
> active object class like you did. I provide active functions, futures,
> method requests, schedulers, and it is up to the user to combine a set of
> active functions with a scheduler and a servant object to produce their
> own full active object.
>
I've implemented a few application specific Active Objects before both
with and without Boost. But now that Boost.Asio + Boost.Threads are
both available in the Boost CVS, the following could very well be a
pattern implementation (untested):
template <const Threads=1>
class active {
boost::asio::io_service _scheduler;
boost::asio::io_service::work _work;
boost::thread_group _threads;
public:
active() : _scheduler(), _work(_scheduler), _threads() {
for (size_t i=0; i < Threads; ++i)
_threads.create_thread(
boost::bind(&boost::asio::io_service::run, &_scheduler) );
};
protected:
~active() {
_scheduler.interrupt();
_threads.join_all();
};
template <typename T>
inline future<T> schedule(boost::function0<T> function) {
future<T> result_;
_scheduler.post(boost::bind(result_, function));
return result_;
};
template <typename T>
inline future<T> sync_schedule(boost::function0<T> function) {
future<T> result_;
_scheduler.post(boost::asio::strand(boost::bind(result_, function)));
return result_;
};
};
To use an implementation like the one above, the idea is that the
class/type that you're making an active object should inherit from the
above implementation:
struct active_writer : active<> {
void write(std::string const & str) {
sync_schedule(boost::bind(&active_writer::write_pimpl, this, str));
};
private:
void write_pimpl(std::string str) {
std::cout << str << std::endl;
};
};
typedef active_writer stdout_log;
// in client code
stdout_log logger;
logger.write("The quick brown fox jumps over the lazy dog."); // exits
immediately
// -------------
This implementation's benefit is that the Active Object pattern
implementation would be easier to apply to user generated types meant
to be active objects. The implementation also requires a future<T>
implementation, which wraps a call to the function and whose function
return is either discarded in case T is void or stored otherwise.
HTH
-- Dean Michael C. Berris http://cplusplus-soup.blogspot.com/ mikhailberis AT gmail DOT com +63 928 7291459
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk