/* -*- C++ -*- */ //============================================================================= /** * @file Token_Handler.h * * $Id$ * * @author Douglas C. Schmidt (schmidt@cs.wustl.edu) Tim Harrison (harrison@cs.wustl.edu) */ //============================================================================= #ifndef ACE_TOKEN_HANDLER_H #define ACE_TOKEN_HANDLER_H #include "ace/Acceptor.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/SOCK_Acceptor.h" #include "ace/Local_Tokens.h" #include "ace/Token_Collection.h" #include "ace/Token_Request_Reply.h" #include "ace/svc_export.h" #if defined (ACE_HAS_TOKENS_LIBRARY) /** * @class ACE_Token_Handler * * @brief Product object created by an . A * exchanges messages with a object * on the client-side. * * This class is the main workhorse of the ACE Token service. It * receives token operation requests from remote clients and turns * them into calls on local tokens (acquire, release, renew, and * remove). In OMG CORBA terms, it is an object adapter. It also * schedules and handles timeouts that are used to support "timed * waits." Clients used timed waits to bound the amount of time * they block trying to get a token. */ class ACE_Svc_Export ACE_Token_Handler : public ACE_Svc_Handler { public: // = Initialization and termination. /// Default constructor. ACE_Token_Handler (ACE_Thread_Manager * = 0); // = Accessor and mutator methods. // = Remote operations "exported" to a client. /** * Try to acquire the token. * Precondition: client *may* hold the token already (i.e., * supports recursive acquisitions). */ virtual int acquire (ACE_Token_Proxy *proxy); /// Try to acquire the token. virtual int try_acquire (ACE_Token_Proxy *proxy); /// Release the token and allow the next client that is waiting to /// proceed. Preconditions: client must hold the token. virtual int release (ACE_Token_Proxy *proxy); /// Yield the token if any clients are waiting, otherwise keep the /// token. Preconditions: client must hold the token. virtual int renew (ACE_Token_Proxy *proxy); /** * Remove the specified token from the Token_Map. Preconditions: * ACE_Token must exist. @@ Any other preconditions, e.g., must * client hold token, must there be no waiters, etc.? */ virtual int remove (ACE_Token_Proxy *proxy); /// Called by TS_[Mutex,RLock,WLock] when we hold the mutex and /// someone wants it. void sleep_hook (void); /// Called by TS_[Mutex,RLock,WLock] when we are waiting and acquire /// the mutex. void token_acquired (ACE_TPQ_Entry *); protected: // = Low level routines for framing requests, dispatching // operations, and returning replies. /// Our connection has been closed. virtual int abandon (int send_error); /// Receive, frame, and decode the client's request. virtual int recv_request (void); /// Dispatch the appropriate operation to handle the client's /// request. virtual int dispatch (void); /// Create and send a reply to the client. virtual int send_reply (ACE_UINT32 errnum); // = Demultiplexing hooks. /// Callback method invoked by the when client events /// arrive. virtual int handle_input (ACE_HANDLE); // = Timer hook. /// Enable clients to limit the amount of time they wait for a token. virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg); /// return a proxy for the calling client_id and token name. ACE_Token_Proxy *get_proxy (void); private: /// Switches on the type of token_request_ and creates a new /// Token_Proxy. virtual ACE_Token_Proxy *create_proxy (void); /// Keeps track of the synchronization options (i.e., the timeout /// interval). ACE_Synch_Options request_options_; /// collection of the client's token proxies. ACE_Token_Collection collection_; /// ID returned by the Reactor that is used to kill registered timers /// when a token operation times out. long timeout_id_; /// Cache request from the client. ACE_Token_Request token_request_; /// Cache reply to the client. ACE_Token_Reply token_reply_; }; // = DESCRIPTION of ACE_TS_* classes: // When Tokens are released, waiting token proxies are notified // when the releasing thread calls token_acquired on the waiting // proxy. The Token Server specializes ACE_Token_Proxy to // redefine the implementation of token_acquired. When // token_acquired is called, the Token_Handler can then send the // response back over the socket connection to unblock the // client side. // Since only the Token_Handler uses ACE_TS_Mutex, we've moved // the definition to the .cpp file. /** * @class ACE_TS_Mutex * * @brief ACE_TS_Mutex -- ACE_*T*oken_*S*erver_Mutex */ class ACE_TS_Mutex : public ACE_Local_Mutex { public: /// Creation. ACE_TS_Mutex (const ACE_TCHAR *name, ACE_Token_Handler *th); protected: /// Somebody wants our token! virtual void sleep_hook (void); /** * We've been taken off the waiters list and given the token! Call * the Token_Handler associated at construction, so it can tell the * remote client. */ virtual void token_acquired (ACE_TPQ_Entry *); /// Duplication. ACE_TS_Mutex (const ACE_TS_Mutex &); /// Return a deep copy. virtual ACE_Token_Proxy *clone (void) const; private: /// The Token Handler associated with this proxy. Set at /// construction and notified when blocking acquires succeed. ACE_Token_Handler* th_; }; /** * @class ACE_TS_RLock * * @brief ACE_TS_RLock -- ACE_*T*oken_*S*erver_RLock */ class ACE_TS_RLock : public ACE_Local_RLock { public: /// Creation. ACE_TS_RLock (const ACE_TCHAR *name, ACE_Token_Handler *th); protected: /// Somebody wants our token! virtual void sleep_hook (void); /** * We've been taken off the waiters list and given the token! Call * the Token_Handler associated at construction, so it can tell the * remote client. */ virtual void token_acquired (ACE_TPQ_Entry *); /// Duplication. ACE_TS_RLock (const ACE_TS_RLock&); /// Return a deep copy. virtual ACE_Token_Proxy *clone (void) const; private: /// the Token Handler associated with this proxy. Set at /// construction and notified when blocking acquires succeed. ACE_Token_Handler* th_; }; /** * @class ACE_TS_WLock * * @brief ACE_TS_WLock -- ACE_*T*oken_*S*erver_WLock */ class ACE_TS_WLock : public ACE_Local_WLock { public: /// Creation. ACE_TS_WLock (const ACE_TCHAR *name, ACE_Token_Handler *th); protected: /// Somebody wants our token! virtual void sleep_hook (void); /** * We've been taken off the waiters list and given the token! Call * the Token_Handler associated at construction, so it can tell the * remote client. */ virtual void token_acquired (ACE_TPQ_Entry *); /// Duplication. ACE_TS_WLock (const ACE_TS_WLock&); /// Return a deep copy. virtual ACE_Token_Proxy *clone (void) const; private: /// the Token Handler associated with this proxy. Set at /// construction and notified when blocking acquires succeed. ACE_Token_Handler* th_; }; /** * @class ACE_Token_Acceptor * * @brief This class contains the service-specific methods that can't * easily be factored into the . */ class ACE_Token_Acceptor : public ACE_Strategy_Acceptor { public: /// Dynamic linking hook. virtual int init (int argc, ACE_TCHAR *argv[]); /// Parse svc.conf arguments. int parse_args (int argc, ACE_TCHAR *argv[]); private: /// The scheduling strategy is designed for Reactive services. ACE_Schedule_All_Reactive_Strategy scheduling_strategy_; }; ACE_SVC_FACTORY_DECLARE (ACE_Token_Acceptor) #endif /* ACE_HAS_TOKENS_LIBRARY */ #endif /* ACE_TOKEN_HANDLER_H */