// . if "forReading" is true call callbacks registered for reading on "fd" // . if "forReading" is false call callbacks registered for writing on "fd" // . if fd is MAX_NUM_FDS and "forReading" is true call all sleepy callbacks void Loop::callCallbacks_ass ( bool forReading , int fd , int64_t now , int32_t niceness ) { // save the g_errno to send to all callbacks int saved_errno = g_errno; ScopedLock sl(m_slotMutex); // get the first Slot in the chain that is waiting on this fd Slot *s ; if ( forReading ) s = m_readSlots [ fd ]; else s = m_writeSlots [ fd ]; //s = m_readSlots [ fd ]; // ensure we called something int32_t numCalled = 0; // . now call all the callbacks // . most will re-register themselves (i.e. call registerCallback...() while ( s ) { // skip this slot if he has no callback if ( ! s->m_callback ) { continue; } // watch out if clock was set back if ( s->m_lastCall > now ) { s->m_lastCall = now; } // if we're a sleep callback, check to make sure not premature if ( fd == MAX_NUM_FDS && s->m_lastCall + s->m_tick > now ) { s = s->m_next; continue; } // skip if not a niceness match if ( niceness == 0 && s->m_niceness != 0 ) { s = s->m_next; continue; } // update the lastCall timestamp for this slot if ( fd == MAX_NUM_FDS ) { s->m_lastCall = now; } // do the callback // NOTE: callback can unregister fd for Slot s, so get next m_callbacksNext = s->m_next; logDebug( g_conf.m_logDebugLoop, "loop: enter fd callback fd=%d nice=%" PRId32, fd, s->m_niceness ); // sanity check. -1 no longer supported if ( s->m_niceness < 0 ) { g_process.shutdownAbort(true); } m_slotMutex.unlock(); s->m_callback ( fd , s->m_state ); m_slotMutex.lock(); logDebug( g_conf.m_logDebugLoop, "loop: exit fd callback fd=%" PRId32" nice=%" PRId32, (int32_t)fd,(int32_t)s->m_niceness ); // inc the flag numCalled++; // reset g_errno so all callbacks for this fd get same g_errno g_errno = saved_errno; // get the next n (will be -1 if no slot after it) s = m_callbacksNext; } m_callbacksNext = NULL; }