ActiveObject support classes
Submitted by pbridger on Tue, 2006-04-18 02:35.
Listing 1. FutureResult
/** FutureResult is parameterised on result type, so we can use this class for all results */ template <typename ResultT> class FutureResult { public: FutureResult() : m_resultReady(false) {} // find whether result can be retrieved yet bool isResultReady() const { boost::mutex::scoped_lock lock(m_mutex); return m_resultReady; } // retrieve result, blocking if not yet available ResultT getResult() { boost::mutex::scoped_lock lock(m_mutex); if(m_resultReady == false) { // block until result becomes available m_resultReadyCondition.wait(lock); } return m_result; } void setResult(const ResultT& result) { boost::mutex::scoped_lock lock(m_mutex); m_result = result; m_resultReady = true; // wake all threads waiting on the result to arrive m_resultReadyCondition.notify_all(); } private: boost::mutex m_mutex; boost::condition m_resultReadyCondition; bool m_resultReady; ResultT m_result; };
Listing 2. MethodRequest and ConcreteMethod
/** Abstract base class allows all ConcreteMethods (possibly with different return types) to be executed polymorphically. This decouples the Activation List from the concrete type of a method request. */ class MethodRequest { public: virtual void execute() = 0; virtual ~MethodRequest(); }; /** The design of ConcreteMethod is strongly coupled to: - FutureResult - the use of boost::shared_ptr for the ref-counted FutureResult - the use of boost::function for the callback type These aspects could have been factored into template parameters, but were coupled (by design) since these components are designed to work together. These additional constraints make them safer and easier to use together. */ template <typename ReturnT> class ConcreteMethod : public MethodRequest { public: typedef boost::function<ReturnT (void)> CallbackT; ConcreteMethod(shared_ptr<FutureResult<ReturnT> > resultFuture, CallbackT callback) : m_resultFuture(resultFuture), m_callback(callback) {} virtual void execute() { // call the callback (which will have been bound to a method on the Servant) // and assign the result to the shared FutureResult object // (making the result available to, and waking, any waiting clients) m_resultFuture->setResult(m_callback()); } private: shared_ptr<FutureResult<ReturnT> > m_resultFuture; CallbackT m_callback; };
