Active Object
The Active Object pattern[1] decouples method invocation and method execution by doing all work in a private per-object thread. Whereas in the Monitor Object pattern interface methods could block, Active Object interface methods return after queueing the relevant processing in an internal "Activation List".
The full Active Object pattern can be quite complex since we need some way of returning method return values, as well as a way to bind method calls to their parameters for deferred execution. Implementations will vary, but conceptually the interface methods will immediately return an object called a "Future", through which the method result may be obtained when the queued processing is completed.
This class diagram shows the Active Object pattern (scheduler component not included for simplicity):

The Proxy provides the Active Object public interface, and runs in the calling thread. It instantiates a Concrete Method implementation object along with the corresponding Future for the result, and these are added to the Activation Queue. The Active Object's private thread will continue to dequeue and execute methods while they are available from the Activation Queue.
An important implementation detail is that Future lifetime is non-trivial - it depends on both the client and the concrete implementation methods. In C++ a good solution is to use a shared pointer so that the Future is cleaned up when there are no more references to it.
Let's have a look at a simplified implementation of the ActiveObject pattern. The servant we are wrapping up has a single function that takes a reasonably long time to run. In fact, the first parameter tells the doSomeWork function how long, in milliseconds, to execute for -- and we'll use this to test the results we get.
Listing 1. Servant interface.
class Servant { public: Servant(); int doSomeWork(unsigned int, bool); };
Now we'll turn this into an ActiveObject, but first let's see how it will be used:
Listing 2. int main
int main(int argc, char* argv[]) { ActiveObjectProxy activeObject; std::cout << "Dispatching...\n"; shared_ptr<FutureResult<int> > result_a = activeObject.doSomeWork(500, false); shared_ptr<FutureResult<int> > result_b = activeObject.doSomeWork(1000, false); shared_ptr<FutureResult<int> > result_c = activeObject.doSomeWork(2000, false); shared_ptr<FutureResult<int> > result_d = activeObject.doSomeWork(4000, false); std::cout << "Waiting for results...\n"; std::cout << result_a->getResult() << "\n"; // outputs 500 after blocking for ~500ms std::cout << result_b->getResult() << "\n"; // outputs 1000 after blocking for an additional ~1000ms std::cout << result_c->getResult() << "\n"; // outputs 2000 after blocking for an additional ~2000ms std::cout << result_d->getResult() << "\n"; // outputs 4000 after blocking for an additional ~4000ms std::cout << "Press <Enter> to continue..."; std::cin.get(); return 0; }
The way the above code should work is that the method request dispatches should execute very quickly, and then the code should block when actually retrieving the results. In a less contrived example, you might be doing other work while periodically polling the FutureResult to see when the method request was complete.
Listing 3. ActiveObjectProxy
/** The ActiveObjectProxy coordinates the behaviour of the ActiveObject including instantiating shared FutureResult instances, binding method request parameters, and adding concrete methods to the activation queue. */ class ActiveObjectProxy { public: ActiveObjectProxy() : m_exit(false) { m_servantThread.reset(new boost::thread(boost::bind(&ActiveObjectProxy::processActivationQueue, this))); } ~ActiveObjectProxy() { // ensure servant thread is shut down { boost::mutex::scoped_lock lock(m_exitMutex); m_exit = true; } m_servantThread->join(); } typedef FutureResult<int> ResultT; typedef shared_ptr<ResultT> RefCountedResultT; typedef boost::function<int (void)> CallbackT; RefCountedResultT doSomeWork(unsigned int inputInteger, bool inputBool) { // instantiate ref-counted FutureResult RefCountedResultT futureResult(new ResultT); // bind parameters to the relevant Servant method CallbackT callback = boost::bind(&Servant::doSomeWork, m_servant, inputInteger, inputBool); // instantiate and enqueue a concrete method request shared_ptr<MethodRequest> concreteMethod(new ConcreteMethod<int>(futureResult, callback)); m_activationQueue.push(concreteMethod); return futureResult; } private: // this method is executed in a private thread, // allowing the servant to do work in the background void processActivationQueue() { while(true) { { boost::mutex::scoped_lock lock(m_exitMutex); if(m_exit) return; } // attempt to unqueue and process the next waiting method request // but don't wait any longer than 100ms const int waitMs = 100; try { m_activationQueue.pop(waitMs)->execute(); } catch(const WaitTimeout&) {} // exceptions should not generally be used for non-exceptional flow control, // but it is a simple, adequate solution for this toy example // a better, but more confusing solution might use boost::optional } } private: Servant m_servant; scoped_ptr<boost::thread> m_servantThread; typedef MonitorQueue<shared_ptr<MethodRequest> > ActivationQueueT; ActivationQueueT m_activationQueue; boost::mutex m_exitMutex; bool m_exit; };
The ActiveObjectProxy coordinates the whole ActiveObject. It binds parameters and enqueues concrete method requests in the activation queue, and also manages the servant thread which processes those method requests.
If you are interested in my generic approach to the FutureResult and ConcreteMethod components, read on.
References
1. Schmidt, D., Stal, M., Rohnert, H., & Buschmann, F. (2000). Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects. Wiley.
