giopstrand.cc

来自「编译工具」· CC 代码 · 共 1,069 行 · 第 1/3 页

CC
1,069
字号
                                // when the giopServer call this function.      }    }  }  if (omniORB::trace(20) && connection) {    omniORB::logger log;    log << (isClient() ? "Client" : "Server")	<< " close connection" 	<< (isClient() ? " to " : " from ")	<< (const char*)peeraddr << "\n";  }  pd_state = DYING;     // satisfy the invariant in the dtor.  delete this;}////////////////////////////////////////////////////////////////////////CORBA::BooleangiopStrand::deletePending(){  ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,1);  return pd_safelyDeleted;}////////////////////////////////////////////////////////////////////////GIOP_S*giopStrand::acquireServer(giopWorker* w){  // Theory of operation:  //  // One or more threads may serve the same strand. However, only  // one thread works on the same GIOP_S instance. This invariant  // is enforced by this function.  //  // There may be one or more GIOP_S instances linked to this  // strand. They can be in one of the following states:  //  //  1. UnUsed*  //        - the instance has not been claimed by any thread  //  2. InputFullyBuffered*  //        - the instance has not been claimed by  //          any thread and a complete message has  //          been received.  //  3. InputPartiallyBuffered**  //        - a message has been partially received. The thread  //          that is currently holding the read lock on this  //          strand may append additional data to this instance.  //          If no thread is holding the read lock, this instance  //          can be claimed by the calling thread.  //  4. Other states***  //        - the instance is currently in used by another thread.  //  //  Note:  //    *   the instance can be claimed by the calling thread  //    **  the instance cannot be claimed by the calling thread unless  //        no other thread is holding the read lock.  //    *** the instance cannot be claimed by the calling thread  //  // This function also acquires the Read lock on the strand if the returned  // giopStream instance is not InputFullyBuffered. (If it is  // InputFullyBuffered, there is no need to read from the strand, hence  // no need for a Read lock.  ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,0);  omni_tracedmutex_lock sync(*omniTransportLock);  if (deletePending()) {    // Check if safeDelete() has been called on the strand and has returned    // true. If this is is the case, we should not proceed or else the    // invarant    //    //    giopStreamList::is_empty(clients) &&    //	  giopStreamList::is_empty(servers) &&    //	  giopStream::noLockWaiting(this)    //         // would be violated.    //    // Notice that giopServer (worker->server()) may schedule any number of    // threads to serve this strand and each of these threads may call this    // function at any time before or after safeDelete() is called and    // returned true.  We use this check to stop all these threads right    // here or else the invarant will be violated.    return 0;  } again:  // Scan the list to identify the 1st occurrance of an instance in  // one of these states: UnUsed, InputFullyBuffered, InputPartiallyBuffered.  GIOP_S* up = 0; // 1st GIOP_S in unused state  GIOP_S* fp = 0; // 1st GIOP_S in InputFullyBuffered state  GIOP_S* pp = 0; // 1st GIOP_S in InputPartiallyBuffered state;  GIOP_S* sp;  giopStreamList* p = servers.next;  while (p != &servers) {    sp = (GIOP_S*)p;    switch (sp->state()) {    case IOP_S::UnUsed:      if (!up) up = sp;      break;    case IOP_S::InputFullyBuffered:      if (!fp) fp = sp;      break;    case IOP_S::InputPartiallyBuffered:      if (!pp) pp = sp;      break;    default:      break;    }    p = p->next;  }  if (fp) {    // This is good, no need to acquire a Read Lock on the strand because    // the whole request message is already in buffer.    sp = fp;  }  else if (giopStream::rdLockNonBlocking(this)) {    // Now we have got the Read Lock, this is *the* thread to read from    // the strand until we release the lock.    // Choose a GIOP_S instance in the following order:    // 1. InputPartiallyBuffered    // 2. UnUsed    // 3. None of the above    if (pp) {      sp = pp;    }    else if (up) {      sp = up;      sp->impl(0);    }    else {      sp = new GIOP_S(this);      sp->giopStreamList::insert(servers);    }    sp->markRdLock();  }  else {    // Another thread is already reading from the strand, we let it does    // the work and let it wake us up if there is some work to do.    giopStream::sleepOnRdLock(this);    goto again;  }  sp->state(IOP_S::Idle);  if (!sp->impl()) {    giopStreamImpl *impl = giopStreamImpl::maxVersion();    sp->impl(impl);    if (version.major == 0)	version = impl->version();  }  // the codeset convertors are filled in by the codeset interceptor  // before a request is unmarshalled.  sp->TCS_C(0);  sp->TCS_W(0);  sp->worker(w);  sp->setDeadline(0,0);  return sp;}////////////////////////////////////////////////////////////////////////voidgiopStrand::releaseServer(IOP_S* iop_s){  omni_tracedmutex_lock sync(*omniTransportLock);  GIOP_S* giop_s = (GIOP_S*) iop_s;  giop_s->rdUnLock();  giop_s->wrUnLock();  giop_s->giopStreamList::remove();  CORBA::Boolean remove = 0;  CORBA::Boolean restart_idle = 1;  if ( state() == giopStrand::DYING ) {    remove = 1;    restart_idle = 0;    // We have to go through the GIOP_S list and delete any ones    // that are in the Unused and InputFullyBuffered states.    // We can also delete the ones in InputPartiallyBuffered state    // if no one is holding the Read lock. See the "theory of operation"    // in acquireServer() for more info.    CORBA::Boolean remove_partial = !giopStream::RdLockIsHeld(this);    giopStreamList* p = servers.next;    while (p != &servers) {      GIOP_S* sp = (GIOP_S*)p;      switch (sp->state()) {      case IOP_S::InputPartiallyBuffered:	if (! remove_partial) break;	// else falls through      case IOP_S::UnUsed:      case IOP_S::InputFullyBuffered:	p = p->next;	sp->giopStreamList::remove();	delete sp;	continue;      default:	break;      }      p = p->next;    }    safeDelete();  }  else if ( !giopStreamList::is_empty(servers) ) {    remove = 1;    giopStreamList* p = servers.next;    while (p != &servers) {      GIOP_S* sp = (GIOP_S*)p;      if (sp->state() > IOP_S::WaitForRequestHeader) {	restart_idle = 0;      }      p = p->next;    }  }  else {    giop_s->state(IOP_S::UnUsed);    giop_s->giopStreamList::insert(servers);  }  if (remove) {    if (giop_s->state() != IOP_S::WaitingForReply)      delete giop_s;    else      restart_idle = 0;  }  if (restart_idle && !biDir) {    CORBA::Boolean success = startIdleCounter();    OMNIORB_ASSERT(success);  }}////////////////////////////////////////////////////////////////////////CORBA::ULonggiopStrand::newSeqNumber() {  ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,1);  seqNumber += 2;  return seqNumber;}////////////////////////////////////////////////////////////////////////StrandList giopStrand::active;StrandList giopStrand::active_timedout;StrandList giopStrand::passive;// Throughout the lifetime of a strand, it is a member of one and only one// of the lists://   active           - the ORB uses this connection in the role of a client//                      it is 'active' in the sense that the connection was//                      initiated by this ORB//   active_timedout  - the connection was previously active and has been//                      idled for some time. It will be deleted soon.//   passive          - the ORB uses this connection in the role of a server//                      it is 'passive' because the connection was initiated//                      by the remote party.//CORBA::ULong giopStrand::idleIncomingBeats = 36;CORBA::ULong giopStrand::idleOutgoingBeats = 24;////////////////////////////////////////////////////////////////////////CORBA::BooleangiopStrand::startIdleCounter() {  ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,1);  if (idlebeats >= 0) {    // The idle counter is already active or has already expired.    return 0;  }  if (isClient()) {    idlebeats = (idleOutgoingBeats) ? (CORBA::Long)idleOutgoingBeats : -1;  }  else {    idlebeats = (idleIncomingBeats) ? (CORBA::Long)idleIncomingBeats : -1;  }  return 1;}////////////////////////////////////////////////////////////////////////CORBA::BooleangiopStrand::stopIdleCounter() {  ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,1);  if (idlebeats == 0) {    // The idle counter has already expired.    return 0;  }  idlebeats = -1;  return 1;}////////////////////////////////////////////////////////////////////////voidScavenger::removeIdle(StrandList& src,StrandList& dest,		      CORBA::Boolean skip_bidir){  StrandList* p = src.next;  while (p != &src) {    giopStrand* s = (giopStrand*)p;    if ( s->idlebeats >= 0 ) {      if (omniORB::trace(30)) {	omniORB::logger log;	log << "Scavenger reduce idle count for strand "	    << (void*)s << " to " << (s->idlebeats - 1) << "\n";      }      if (--(s->idlebeats) <= 0) {	p = p->next;	s->StrandList::remove();	s->RopeLink::remove();	s->StrandList::insert(dest);	continue;      }    }    p = p->next;  }}////////////////////////////////////////////////////////////////////////voidScavenger::execute(){  omniORB::logs(25, "Scavenger task execute.");  unsigned long abs_sec,abs_nsec;  omni_thread::get_time(&abs_sec,&abs_nsec);  while (1) {    {      omni_tracedmutex_lock sync(*mutex);      if ( shutdown || !orbParameters::scanGranularity ) {	goto died;      }      omni_thread::get_time(&abs_sec,&abs_nsec,orbParameters::scanGranularity);      cond->timedwait(abs_sec,abs_nsec);    }    if (omniORB::trace(30)) {      omniORB::logger log;      log << "Scan for idle connections ("	  << abs_sec << "," << abs_nsec << ")\n";    }    StrandList client_shutdown_list;    StrandList server_shutdown_list;    {      // Collect all the strands that should be removed      // We want to minimise the time we hold the omniTransportLock.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?