Main Page   Modules   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages   Examples  

CTBsignalBase.cxx

Go to the documentation of this file.
00001 
00006 /*----------------------------------------------------------------------------*/
00007 /* C Tool Box: Designed and implemented by:                                   */
00008 /*    Walter F.J. Mueller   Gesellschaft fuer Schwerionenforschung (GSI)      */
00009 /*                          Planckstrasse 1, D-64291 Darmstadt, Germany       */
00010 /*                  Email:  W.F.J.Mueller@gsi.de                              */
00011 /*                  WWW:    http://www-kp3.gsi.de/www/kp3/people/mueller.html */
00012 /*------------------------------------------+---------------------------------*/
00013 
00014 #include <assert.h>
00015 
00016 #include "CTB.hxx"
00017 #include "CTB_Trace.hxx"
00018 
00019 #include "CTBsignalBase.hxx"
00020 
00026 //------------------------------------------+-----------------------------------
00028 
00029 CTBsignalEmitter::~CTBsignalEmitter()
00030 {
00031   CTB_Trace("~CTBsignalEmitter()");
00032 
00033   while(m_ehead) {
00034     CTBsignalLink*         p_link = m_ehead.First();    
00035     CTBsignalReceiverBase* p_receiver = p_link->m_rlink.Parent();
00036 
00037     p_link->UnlinkEmitter();                // unlink from emitter queue
00038 
00039     if (p_receiver) {                       // receiver still connected 
00040       if (p_receiver->Blocked()) {          // if blocked, queue it
00041         p_link->mi_pendingmask = 0;
00042         if (!p_link->Pending()) {
00043           p_link->m_plink.InsertTail(p_link, &CTBsignalLink::m_plink,
00044                                      p_receiver->m_phead);
00045         }
00046 
00047       } else {                              // if not blocked, deliver
00048         p_link->Mark();
00049         try {
00050           p_receiver->Execute(p_link->mp_emitter,0); // DO IT !!
00051         } catch(...) {                      // simply drop exception 
00052         }
00053         p_link->Unmark();
00054       }
00055     }
00056 
00057     if (!p_link->Busy() && !p_link->Pending()) delete p_link; // burry zombie
00058   }
00059 }
00060 
00061 //------------------------------------------+-----------------------------------
00063 
00064 int CTBsignalEmitter::NConnect() const
00065 {
00066   CTB_Trace("CTBsignalEmitter::NConnect()");
00067 
00068   int i_nconnect = 0;
00069   
00070   for(CTBsignalLink* p_link = m_ehead.First(); p_link;
00071                      p_link = p_link->m_elink.Next()) {
00072     if (!p_link->Zombie()) i_nconnect++;
00073   }
00074   
00075   return i_nconnect;
00076 }
00077 
00078 //------------------------------------------+-----------------------------------
00080 
00081 void CTBsignalEmitter::Execute(CTBuint32 i_mask) const
00082 {
00083   CTB_Trace("CTBsignalEmitter::Execute(CTBuint32)");
00084 
00085   if (i_mask == 0) return;                  // drop empty requests
00086 
00087   for(CTBsignalLink* p_link = m_ehead.First(); p_link; ) {
00088     CTBsignalLink*         p_next = p_link->m_elink.Next();
00089     CTBsignalReceiverBase* p_receiver = p_link->m_rlink.Parent();
00090 
00091     if (i_mask & p_link->mi_acceptmask) {   // any interest ?
00092 
00093       if (p_receiver) {                     // if still connected
00094         if (p_receiver->Blocked()) {        // if blocked, queue it
00095           if (p_link->Pending()) {          // already pending signals ?
00096             assert(p_link->mi_pendingmask != 0); // !?! connect&pend-> !0 mask
00097             p_link->mi_pendingmask |= i_mask;
00098           } else {
00099             assert(p_link->mi_pendingmask == 0); // !?! !pending -> 0 mask
00100             p_link->mi_pendingmask = i_mask;
00101             p_link->m_plink.InsertTail(p_link, &CTBsignalLink::m_plink,
00102                                        p_receiver->m_phead);
00103           }
00104           
00105         } else {                            // if not blocked, deliver  
00106           p_link->Mark();                   // lock link against deletion
00107           try {
00108             p_receiver->Execute(p_link->mp_emitter,i_mask); // DO IT !!
00109             
00110           } catch(...) {                    // simply drop exception
00111           }
00112           p_link->Unmark();                 // unlock
00113         }
00114         
00115         p_next = p_link->m_elink.Next();    // re-evaluate in case of deletions
00116         if (p_link->Deletable()) delete p_link; // burry zombie if possible
00117       }
00118     }
00119     
00120     p_link = p_next;
00121   }
00122 
00123   return;
00124 }
00125 
00126 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00127 
00133 //------------------------------------------+-----------------------------------
00135 
00136 CTBsignalReceiverBase::~CTBsignalReceiverBase()
00137 {
00138   CTB_Trace("~CTBsignalReceiverBase()");
00139 
00140   Disconnect();
00141 }
00142 
00143 //------------------------------------------+-----------------------------------
00145 
00146 int CTBsignalReceiverBase::NConnect() const
00147 {
00148   CTB_Trace("CTBsignalReceiverBase::NConnect()");
00149 
00150   int i_nconnect = 0;
00151   
00152   for(CTBsignalLink* p_link = m_rhead.First(); p_link;
00153                      p_link = p_link->m_rlink.Next()) {
00154     if (!p_link->Zombie()) i_nconnect++;
00155   }
00156   
00157   return i_nconnect;
00158 }
00159 
00160 //------------------------------------------+-----------------------------------
00162 
00163 void CTBsignalReceiverBase::Disconnect()
00164 {
00165   CTB_Trace("CTBsignalReceiverBase::Disconnect()");
00166 
00167   while (m_rhead) {
00168     CTBsignalLink* p_link = m_rhead.First();
00169     
00170     if (p_link->Busy()) {
00171       p_link->UnlinkReceiver();
00172     } else {
00173       delete p_link;
00174     }
00175   }
00176   
00177   return;
00178 }
00179 
00180 //------------------------------------------+-----------------------------------
00182 
00183 void CTBsignalReceiverBase::Disconnect(CTBsignalEmitter& emitter)
00184 {
00185   CTB_Trace("CTBsignalReceiverBase::Disconnect(CTBsignalEmitter&)");
00186 
00187   for (CTBsignalLink* p_link = m_rhead.First(); p_link; ) {
00188     CTBsignalLink* p_next = p_link->m_rlink.Next();
00189 
00190     if (p_link->m_elink.Head() == &emitter.m_ehead) {
00191       if (p_link->Busy()) {
00192         p_link->UnlinkReceiver();
00193       } else {
00194         delete p_link;
00195       }
00196     }
00197     p_link = p_next;
00198   }
00199   
00200   return;
00201 }
00202 
00203 // Notes:
00204 //  1. p_next must be evaluated before the Link object is deleted !!
00205 
00206 //------------------------------------------+-----------------------------------
00208 
00209 void CTBsignalReceiverBase::Deliver()
00210 {
00211   CTB_Trace("CTBsignalReceiverBase::Deliver()");
00212 
00213   while (m_phead) {
00214     CTBsignalLink* p_link = m_phead.First();
00215 
00216     p_link->m_plink.Remove(&CTBsignalLink::m_plink);
00217     
00218     try {
00219       CTBuint32 i_mask=p_link->mi_pendingmask;
00220 
00221       p_link->mi_pendingmask = 0;           // reset mask of delivered signals
00222       Execute(p_link->mp_emitter, i_mask);
00223       
00224     } catch(...) {                          // simply drop exception
00225     }
00226 
00227   }
00228 
00229   return;
00230 }
00231 
00232 // Notes:
00233 //  1. One has to first save the pending signal mask, than clear it, and finally
00234 //     call Execute() because the signal handler can reemit this signal, with
00235 //     the same or potentially a different mask. The algorithm guarantees that
00236 //     each signal mask bit is delivered at least once.
00237 
00238 //------------------------------------------+-----------------------------------
00240 
00241 CTBsignalReceiverBase& CTBsignalReceiverBase::operator=(
00242     const CTBsignalReceiverBase& rhs)
00243 {
00244   CTB_Trace("CTBsignalReceiverBase::operator=(const CTBsignalReceiverBase&)");
00245 
00246   if (this == &rhs) return *this;
00247   
00248   Disconnect();
00249  
00250   mi_nblock = rhs.mi_nblock;
00251 
00252   for (CTBsignalLink* p_link = rhs.m_rhead.First(); p_link;
00253        p_link = p_link->m_rlink.Next()) {
00254     if (!p_link->Zombie()) {
00255       new CTBsignalLink(*p_link, *this);
00256     }
00257   }
00258   
00259   return *this;
00260 }
00261 
00262 //------------------------------------------+-----------------------------------
00264 
00265 void CTBsignalReceiverBase::Connect(CTBsignalEmitter& emitter,
00266                                     void* p_emitter, CTBuint32 i_mask)
00267 {
00268   CTB_Trace("CTBsignalReceiverBase::Connect(CTBsignalEmitter&, void*, CTBuint32)");
00269 
00270   new CTBsignalLink(emitter, *this, p_emitter, i_mask);
00271   return;
00272 }
00273 
00274 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00275 
00276 #ifdef DEV_DOCS
00277 
00281 #endif
00282 
00283 //------------------------------------------+-----------------------------------
00285 
00286 CTBsignalLink::CTBsignalLink(CTBsignalEmitter& emitter,
00287                              CTBsignalReceiverBase& receiver,
00288                              void* p_emitter, CTBuint32 i_mask)
00289   : m_elink(),
00290     m_rlink(),
00291     m_plink(),
00292     mi_nbusy(0),
00293     mp_emitter(p_emitter),
00294     mi_acceptmask(i_mask),
00295     mi_pendingmask(0)
00296 {
00297   CTB_Trace("CTBsignalLink(CTBsignalEmitter&, CTBsignalReceiverBase&, void*, CTBuint32)");
00298 
00299   m_elink.InsertTail(this, &CTBsignalLink::m_elink, emitter.m_ehead);
00300   m_rlink.InsertTail(this, &CTBsignalLink::m_rlink, 
00301                      receiver, &CTBsignalReceiverBase::m_rhead);
00302 }
00303 
00304 //------------------------------------------+-----------------------------------
00306 
00307 CTBsignalLink::CTBsignalLink(const CTBsignalLink& rhs,
00308                              CTBsignalReceiverBase& receiver)
00309   : m_elink(),
00310     m_rlink(),
00311     m_plink(),
00312     mi_nbusy(0),
00313     mp_emitter(rhs.mp_emitter),
00314     mi_acceptmask(rhs.mi_acceptmask),
00315     mi_pendingmask(rhs.mi_pendingmask)
00316 {
00317   CTB_Trace("CTBsignalLink(const CTBsignalLink&, CTBsignalReceiverBase&)");
00318 
00319   m_elink.InsertTail(this, &CTBsignalLink::m_elink, *rhs.m_elink.Head());
00320   m_rlink.InsertTail(this, &CTBsignalLink::m_rlink, 
00321                      receiver, &CTBsignalReceiverBase::m_rhead);
00322   if (rhs.Pending()) m_plink.InsertTail(this, &CTBsignalLink::m_plink,
00323                                         receiver.m_phead);
00324 }
00325 
00326 //------------------------------------------+-----------------------------------
00328 
00329 CTBsignalLink::~CTBsignalLink()
00330 {
00331   CTB_Trace("~CTBsignalLink()");
00332   
00333   assert(mi_nbusy == 0);                    // !?! must not be busy
00334   UnlinkEmitter();
00335   UnlinkReceiver();
00336 }
00337 
00338 //------------------------------------------+-----------------------------------

Generated at Fri Oct 24 18:11:30 2003 for CTBbase by doxygen1.2.9-20010812 written by Dimitri van Heesch, © 1997-2001