Boost logo

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