/* -*- C++ -*- */ // $Id$ // ============================================================================ // // = LIBRARY // ace // // = FILENAME // Future.h // // = AUTHOR // Andres Kruse , // Douglas C. Schmidt , // Per Andersson , and // John Tucker // // ============================================================================ #ifndef ACE_FUTURE_H #define ACE_FUTURE_H #include "ace/Synch.h" #include "ace/Strategies_T.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #if defined (ACE_HAS_THREADS) // Forward decl. template class ACE_Future_Holder; template class ACE_Future_Observer; template class ACE_Future_Rep; template class ACE_Future; template class ACE_Export ACE_Future_Holder { // = TITLE // Implementation of object which has holds ACE_Future. public: ACE_Future_Holder (const ACE_Future &future); ~ACE_Future_Holder (void); ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. ACE_Future item_; protected: ACE_Future_Holder (void); }; template class ACE_Future_Observer { // = TITLE // ACE_Future_Observer // // = DESCRIPTION // An ACE_Future_Observer object implements an object that is // subscribed with an ACE_Future object so that it may be // notified when the value of the ACE_Future object is // written to by a writer thread. // // It uses the Observer pattern public: // = Destructor virtual ~ACE_Future_Observer (void); virtual void update(const ACE_Future &future) = 0; // Called by the ACE_Future in which we are subscribed to when // its value is written to. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. protected: // = Constructor ACE_Future_Observer (void); }; template class ACE_Future_Rep { // = TITLE // ACE_Future_Rep // // = DESCRIPTION // An ACE_Future_Rep object encapsules a pointer to an object // of class T which is the result of an asynchronous method // invocation. It is pointed to by ACE_Future object[s] and // only accessible through them. private: friend class ACE_Future; int set (const T &r, ACE_Future &caller); // Set the result value. The specified represents the // future that invoked this method, which is used to notify // the list of future observers. int get (T &value, ACE_Time_Value *tv); // Wait up to time to get the . Note that must be // specified in absolute time rather than relative time. int attach (ACE_Future_Observer *observer, ACE_Future &caller); // Attaches the specified observer to a subject (i.e. the // ACE_Future_Rep). The update method of the specified subject will // be invoked with a copy of the written-to ACE_Future as input when // the result gets set. // // Returns 0 if the observer is successfully attached, 1 if the // observer is already attached, and -1 if failures occur. int detach (ACE_Future_Observer *observer); // Detaches the specified observer from a subject (i.e. the // ACE_Future_Rep). The update method of the specified subject will // not be invoked when the ACE_Future_Reps result gets set. Returns // 1 if the specified observer was actually attached to the subject // prior to this call and 0 if was not. // // Returns 0 if the observer was successfully detached, and -1 if the observer was // not attached in the first place. operator T (); // Type conversion. will block forever until the result is // available. Note that this method is going away in a subsequent // release since it doesn't distinguish between failure results and // success results (exceptions should be used, but they aren't // portable...). The method should be used instead since it // separates the error value from the result, and also permits // timeouts. void dump (void) const; // Dump the state of an object. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. // = Constructor and destructor private ACE_Future_Rep (void); ~ACE_Future_Rep (void); int ready (void); // Is result available? // = Handle ref counting and object lifetime for ACE_Future_Rep. // These methods must go after the others to work around a bug with // Borland's C++ Builder. static ACE_Future_Rep *create (void); // Create a ACE_Future_Rep and initialize the reference count. static ACE_Future_Rep *attach (ACE_Future_Rep *&rep); // Increase the reference count and return argument. Uses the // attribute "value_ready_mutex_" to synchronize reference count // updating. // // Precondition(rep != 0). static void detach (ACE_Future_Rep *&rep); // Decreases the reference count and and deletes rep if there are no // more references to rep. // // Precondition(rep != 0) static void assign (ACE_Future_Rep *&rep, ACE_Future_Rep *new_rep); // Decreases the rep's reference count and and deletes rep if there // are no more references to rep. Then assigns new_rep to rep. // // Precondition(rep != 0 && new_rep != 0) T *value_; // Pointer to the result. int ref_count_; // Reference count. typedef ACE_Future_Observer OBSERVER; typedef ACE_Unbounded_Set OBSERVER_COLLECTION; OBSERVER_COLLECTION observer_collection_; // Keep a list of ACE_Future_Observers unread by client's reader thread. // = Condition variable and mutex that protect the . ACE_Condition_Thread_Mutex value_ready_; ACE_Thread_Mutex value_ready_mutex_; }; template class ACE_Future { // = TITLE // This class implements a ``single write, multiple read'' // pattern that can be used to return results from asynchronous // method invocations. public: // = Initialization and termination methods. ACE_Future (void); // Constructor. ACE_Future (const ACE_Future &r); // Copy constructor binds and to the same // . An is created if necessary. ACE_Future (const T &r); // Constructor that initialises an to point to the // result immediately. ~ACE_Future (void); // Destructor. void operator = (const ACE_Future &r); // Assignment operator that binds and to the same // . An is created if necessary. int cancel (const T &r); // Cancel an and assign the value . It is used if a // client does not want to wait for to be produced. int cancel (void); // Cancel an . Put the future into its initial // state. Returns 0 on succes and -1 on failure. It is now possible // to reuse the ACE_Future. But remember, the ACE_Future // is now bound to a new ACE_Future_Rep. int operator == (const ACE_Future &r) const; // Equality operator that returns 1 if both ACE_Future objects // point to the same ACE_Future_Rep object. Attention: It also // returns 1 if both objects have just been instantiated and not // used yet. int operator != (const ACE_Future &r) const; // Inequality operator, which is the opposite of equality. int set (const T &r); // Make the result available. Is used by the server thread to give // the result to all waiting clients. int get (T &value, ACE_Time_Value *tv = 0); // Wait up to time to get the . Note that must be // specified in absolute time rather than relative time. operator T (); // Type conversion, which obtains the result of the asynchronous // method invocation. Will block forever. Note that this method is // going away in a subsequent release since it doesn't distinguish // between failure results and success results (exceptions should be // used, but they aren't portable...). The method should be // used instead since it separates the error value from the result, // and also permits timeouts. int ready (void); // Check if the result is available. int attach (ACE_Future_Observer *observer); // Attaches the specified observer to a subject (i.e. the // ACE_Future). The update method of the specified subject will be // invoked with a copy of the associated ACE_Future as input when // the result gets set. If the result is already set when this // method gets invoked, then the update method of the specified // subject will be invoked immediately. // // Returns 0 if the observer is successfully attached, 1 if the // observer is already attached, and -1 if failures occur. int detach (ACE_Future_Observer *observer); // Detaches the specified observer from a subject (i.e. the // ACE_Future_Rep). The update method of the specified subject will // not be invoked when the ACE_Future_Reps result gets set. Returns // 1 if the specified observer was actually attached to the subject // prior to this call and 0 if was not. // // Returns 0 if the observer was successfully detached, and -1 if the observer was // not attached in the first place. void dump (void) const; // Dump the state of an object. ACE_Future_Rep *get_rep(); // Get the underlying ACE_Future_Rep*. Note that this method should // rarely, if ever, be used and that modifying the undlerlying ACE_Future_Rep* // should be done with extreme caution. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. private: void *operator new (size_t nbytes); // Do not allow new operator. void operator delete (void *); // Do not allow delete operator void operator &(); // Do not allow address-of operator. // the ACE_Future_Rep typedef ACE_Future_Rep FUTURE_REP; FUTURE_REP *future_rep_; // Protect operations on the . }; #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) #include "ace/Future.cpp" #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation ("Future.cpp") #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ #endif /* ACE_HAS_THREADS */ #endif /* ACE_FUTURE_H */