00001 // -*- C++ -*- 00002 // 00003 // Dev_Poll_Reactor.inl,v 4.8 2005/10/28 16:14:52 ossama Exp 00004 00005 #include "ace/Log_Msg.h" 00006 00007 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00008 00009 ACE_INLINE 00010 ACE_Dev_Poll_Event_Tuple::ACE_Dev_Poll_Event_Tuple (void) 00011 : event_handler (0), 00012 mask (ACE_Event_Handler::NULL_MASK), 00013 suspended (0) 00014 { 00015 } 00016 00017 // --------------------------------------------------------------------- 00018 00019 #if 0 00020 ACE_INLINE 00021 ACE_Dev_Poll_Ready_Set::ACE_Dev_Poll_Ready_Set (void) 00022 : pfds (0), 00023 nfds (0) 00024 { 00025 } 00026 #endif /* 0 */ 00027 00028 // --------------------------------------------------------------------- 00029 00030 ACE_INLINE void 00031 ACE_Dev_Poll_Reactor_Handler_Repository::mask (ACE_HANDLE handle, 00032 ACE_Reactor_Mask mask) 00033 { 00034 ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::mask"); 00035 00036 // Only bother to search for the handle if it's in range. 00037 if (this->handle_in_range (handle)) 00038 this->handlers_[handle].mask = mask; 00039 } 00040 00041 ACE_INLINE ACE_Reactor_Mask 00042 ACE_Dev_Poll_Reactor_Handler_Repository::mask (ACE_HANDLE handle) 00043 { 00044 ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::mask"); 00045 00046 ACE_Reactor_Mask mask = ACE_Event_Handler::NULL_MASK; 00047 00048 // Only bother to search for the handle if it's in range. 00049 if (this->handle_in_range (handle)) 00050 mask = this->handlers_[handle].mask; 00051 00052 if (mask == ACE_Event_Handler::NULL_MASK) 00053 errno = ENOENT; 00054 00055 return mask; 00056 } 00057 00058 ACE_INLINE void 00059 ACE_Dev_Poll_Reactor_Handler_Repository::suspend (ACE_HANDLE handle) 00060 { 00061 ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::suspend"); 00062 00063 // Only bother to search for the handle if it's in range. 00064 if (this->handle_in_range (handle)) 00065 this->handlers_[handle].suspended = 1; 00066 } 00067 00068 ACE_INLINE void 00069 ACE_Dev_Poll_Reactor_Handler_Repository::resume (ACE_HANDLE handle) 00070 { 00071 ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::resume"); 00072 00073 // Only bother to search for the handle if it's in range. 00074 if (this->handle_in_range (handle)) 00075 this->handlers_[handle].suspended = 0; 00076 } 00077 00078 ACE_INLINE int 00079 ACE_Dev_Poll_Reactor_Handler_Repository::suspended (ACE_HANDLE handle) const 00080 { 00081 ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::suspended"); 00082 00083 if (this->handle_in_range (handle)) 00084 return this->handlers_[handle].suspended; 00085 00086 return -1; 00087 } 00088 00089 ACE_INLINE size_t 00090 ACE_Dev_Poll_Reactor_Handler_Repository::size (void) const 00091 { 00092 ACE_TRACE ("ACE_Dev_Poll_Reactor_Handler_Repository::size"); 00093 00094 return this->max_size_; 00095 } 00096 00097 // ----------------------------------------------------------------- 00098 00099 ACE_INLINE 00100 ACE_Dev_Poll_Handler_Guard::ACE_Dev_Poll_Handler_Guard 00101 (ACE_Event_Handler *eh, 00102 bool do_incr) 00103 : eh_ (eh), 00104 refcounted_ (false) 00105 { 00106 if (eh == 0) 00107 return; 00108 00109 this->refcounted_ = 00110 eh->reference_counting_policy ().value () == 00111 ACE_Event_Handler::Reference_Counting_Policy::ENABLED; 00112 00113 if (do_incr && this->refcounted_) 00114 eh->add_reference (); 00115 00116 /** 00117 * The below comments were here when I replaced the old refcount 00118 * scheme was replaced. They may still need addressing. -Steve Huston 00119 */ 00120 00121 /** 00122 * @todo Suspend the handler so that other threads will not cause 00123 * an event that is already in an upcall from being dispatched 00124 * again. 00125 * 00126 * @note The naive approach would be to simply call 00127 * suspend_handler_i() on the reactor. However, that would 00128 * cause a system call (write()) to occur. Obviously this 00129 * can potentially have an adverse affect on performance. 00130 * Ideally, the handler would only be marked as "suspended" in 00131 * the handler repository. If an event arrives for a 00132 * suspended handler that event can be "queued" in a 00133 * "handle readiness queue." "Queued" is quoted since a real 00134 * queue need not be used since duplicate events can be 00135 * coalesced, thus avoiding unbounded queue growth. Event 00136 * coalescing is already done by Linux's event poll driver 00137 * (/dev/epoll) so Solaris' poll driver (/dev/poll) is the 00138 * main concern here. The largest the queue can be is the 00139 * same size as the number of handlers stored in the handler 00140 * repository. 00141 */ 00142 } 00143 00144 ACE_INLINE 00145 ACE_Dev_Poll_Handler_Guard::~ACE_Dev_Poll_Handler_Guard (void) 00146 { 00147 if (this->refcounted_ && this->eh_ != 0) 00148 this->eh_->remove_reference (); 00149 00150 /** 00151 * The below comments were here when I replaced the old refcount 00152 * scheme was replaced. They may still need addressing. -Steve Huston 00153 */ 00154 /** 00155 * @todo Resume the handler so that other threads will be allowed to 00156 * dispatch the handler. 00157 */ 00158 } 00159 00160 ACE_INLINE void 00161 ACE_Dev_Poll_Handler_Guard::release (void) 00162 { 00163 this->eh_ = 0; 00164 } 00165 00166 // --------------------------------------------------------------------- 00167 00168 ACE_INLINE int 00169 ACE_Dev_Poll_Reactor::upcall (ACE_Event_Handler *event_handler, 00170 int (ACE_Event_Handler::*callback)(ACE_HANDLE), 00171 ACE_HANDLE handle) 00172 { 00173 // If the handler returns positive value (requesting a reactor 00174 // callback) just call back as many times as the handler requests 00175 // it. Other threads are off handling other things. 00176 int status = 0; 00177 00178 do 00179 { 00180 status = (event_handler->*callback) (handle); 00181 } 00182 while (status > 0); 00183 00184 return status; 00185 } 00186 00187 00188 /************************************************************************/ 00189 // Methods for ACE_Dev_Poll_Reactor::Token_Guard 00190 /************************************************************************/ 00191 00192 ACE_INLINE 00193 ACE_Dev_Poll_Reactor::Token_Guard::Token_Guard (ACE_Dev_Poll_Reactor_Token &token) 00194 00195 : token_ (token), 00196 owner_ (0) 00197 { 00198 } 00199 00200 ACE_INLINE 00201 ACE_Dev_Poll_Reactor::Token_Guard::~Token_Guard (void) 00202 { 00203 if (this->owner_ == 1) 00204 { 00205 ACE_MT (this->token_.release ()); 00206 this->owner_ = 0; 00207 } 00208 } 00209 00210 ACE_INLINE void 00211 ACE_Dev_Poll_Reactor::Token_Guard::release_token (void) 00212 { 00213 if (this->owner_) 00214 { 00215 ACE_MT (this->token_.release ()); 00216 00217 // We are not the owner anymore.. 00218 this->owner_ = 0; 00219 } 00220 } 00221 00222 ACE_INLINE int 00223 ACE_Dev_Poll_Reactor::Token_Guard::is_owner (void) 00224 { 00225 return this->owner_; 00226 } 00227 00228 ACE_END_VERSIONED_NAMESPACE_DECL