#include <ace/Select_Reactor.h>
class ACE_Select_Reactor_Token : public ACE_SELECT_REACTOR_MUTEX {
public:
ACE_Select_Reactor_Token (ACE_Select_Reactor &r);
ACE_Select_Reactor_Token (void);
virtual ~ACE_Select_Reactor_Token (void);
virtual void sleep_hook (void);
ACE_Select_Reactor &select_reactor (void);
void select_reactor (ACE_Select_Reactor &);
void dump (void) const;
ACE_ALLOC_HOOK_DECLARE;
private:
ACE_Select_Reactor *select_reactor_;
};
ACE_Select_Reactor
thread-safe. By default, the thread that runs the
handle_events
loop holds the token, even when it is blocked
in the select
call. Whenever another thread wants to
access the ACE_Reactor
via its register_handler
,
remove_handler
, etc. methods) it must ask the token owner
for temporary release of the token. To accomplish this, the
owner of a token must define a sleep_hook
through which it
can be notified to temporarily release the token if the
current situation permits this.
The owner of the token is responsible for deciding which
request for the token can be granted. By using the
ACE_Token::renew
API, the thread that releases the token
temporarily can specify to get the token back right after the
other thread has completed using the token. Thus, there is a
dedicated thread that owns the token ``by default.'' This
thread grants other threads access to the token by ensuring
that whenever somebody else has finished using the token the
``default owner'' first holds the token again, i.e., the
owner has the chance to schedule other threads.
The thread that most likely needs the token most of the time
is the thread running the dispatch loop. Typically the token
gets released prior to entering the select
call and gets
``re-acquired'' as soon as the select
call returns, which
results probably in many calls to release
/acquire
that
are not really needed since no other thread would need the
token in the meantime. That's why the dispatcher thread is
chosen to be the owner of the token.
In case the token would have been released while in select
there would be a good chance that the fd_set
could have
been modified while the select
returns from blocking and
trying to re-acquire the lock. Through the token mechanism
it is ensured that while another thread is holding the token,
the dispatcher thread is blocked in the renew
call and not
in select
. Thus, it is not critical to change the
fd_set
. The implementation of the sleep_hook
mechanism
provided by the ACE_Select_Reactor_Token
enables the
default owner to be the thread that executes the dispatch
loop.
ACE_Select_Reactor_Token (ACE_Select_Reactor &r);
ACE_Select_Reactor_Token (void);
virtual ~ACE_Select_Reactor_Token (void);
virtual void sleep_hook (void);
ACE_Select_Reactor &select_reactor (void);
void select_reactor (ACE_Select_Reactor &);
void dump (void) const;
ACE_ALLOC_HOOK_DECLARE;
ACE_Select_Reactor *select_reactor_;