
On 3/6/07, Frank Mori Hess <frank.hess@nist.gov> 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