diff --git a/ext/cmain.cpp b/ext/cmain.cpp index 982b095b3..6b24a6492 100644 --- a/ext/cmain.cpp +++ b/ext/cmain.cpp @@ -833,3 +833,14 @@ extern "C" int evma_set_heartbeat_interval(float interval) ensure_eventmachine("evma_set_heartbeat_interval"); return EventMachine->SetHeartbeatInterval(interval); } + + +/************************** +evma_get_current_loop_time +***************************/ + +extern "C" uint64_t evma_get_current_loop_time() +{ + ensure_eventmachine("evma_get_current_loop_time"); + return EventMachine->GetCurrentTime(); +} \ No newline at end of file diff --git a/ext/ed.cpp b/ext/ed.cpp index ca73fbb5a..cc0a1d8d3 100644 --- a/ext/ed.cpp +++ b/ext/ed.cpp @@ -88,12 +88,13 @@ EventableDescriptor::EventableDescriptor (int sd, EventMachine_t *em): throw std::runtime_error ("bad eventable descriptor"); if (MyEventMachine == NULL) throw std::runtime_error ("bad em in eventable descriptor"); - CreatedAt = gCurrentLoopTime; + CreatedAt = MyEventMachine->GetCurrentTime(); #ifdef HAVE_EPOLL EpollEvent.events = 0; EpollEvent.data.ptr = this; #endif + LastActivity = MyEventMachine->GetCurrentTime(); } @@ -256,7 +257,7 @@ EventableDescriptor::SetPendingConnectTimeout int EventableDescriptor::SetPendingConnectTimeout (float value) { if (value > 0) { - PendingConnectTimeout = (Int64)(value * 1000000); + PendingConnectTimeout = (uint64_t)(value * 1000000); return 1; } return 0; @@ -287,7 +288,6 @@ ConnectionDescriptor::ConnectionDescriptor (int sd, EventMachine_t *em): bGotExtraKqueueEvent(false), #endif bIsServer (false), - LastIo (gCurrentLoopTime), InactivityTimeout (0) { // 22Jan09: Moved ArmKqueueWriter into SetConnectPending() to fix assertion failure in _WriteOutboundData() @@ -637,7 +637,7 @@ void ConnectionDescriptor::Read() return; } - LastIo = gCurrentLoopTime; + LastActivity = MyEventMachine->GetCurrentTime(); int total_bytes_read = 0; char readbuffer [16 * 1024 + 1]; @@ -843,7 +843,7 @@ void ConnectionDescriptor::_WriteOutboundData() return; } - LastIo = gCurrentLoopTime; + LastActivity = MyEventMachine->GetCurrentTime(); size_t nbytes = 0; #ifdef HAVE_WRITEV @@ -1147,12 +1147,12 @@ void ConnectionDescriptor::Heartbeat() */ if (bConnectPending) { - if ((gCurrentLoopTime - CreatedAt) >= PendingConnectTimeout) + if ((MyEventMachine->GetCurrentTime() - CreatedAt) >= PendingConnectTimeout) ScheduleClose (false); //bCloseNow = true; } else { - if (InactivityTimeout && ((gCurrentLoopTime - LastIo) >= InactivityTimeout)) + if (InactivityTimeout && ((MyEventMachine->GetCurrentTime() - LastActivity) >= InactivityTimeout)) ScheduleClose (false); //bCloseNow = true; } @@ -1363,7 +1363,6 @@ DatagramDescriptor::DatagramDescriptor DatagramDescriptor::DatagramDescriptor (int sd, EventMachine_t *parent_em): EventableDescriptor (sd, parent_em), OutboundDataSize (0), - LastIo (gCurrentLoopTime), InactivityTimeout (0) { memset (&ReturnAddress, 0, sizeof(ReturnAddress)); @@ -1418,7 +1417,7 @@ void DatagramDescriptor::Heartbeat() { // Close it if its inactivity timer has expired. - if (InactivityTimeout && ((gCurrentLoopTime - LastIo) >= InactivityTimeout)) + if (InactivityTimeout && ((MyEventMachine->GetCurrentTime() - LastActivity) >= InactivityTimeout)) ScheduleClose (false); //bCloseNow = true; } @@ -1432,7 +1431,7 @@ void DatagramDescriptor::Read() { int sd = GetSocket(); assert (sd != INVALID_SOCKET); - LastIo = gCurrentLoopTime; + LastActivity = MyEventMachine->GetCurrentTime(); // This is an extremely large read buffer. // In many cases you wouldn't expect to get any more than 4K. @@ -1509,7 +1508,7 @@ void DatagramDescriptor::Write() int sd = GetSocket(); assert (sd != INVALID_SOCKET); - LastIo = gCurrentLoopTime; + LastActivity = MyEventMachine->GetCurrentTime(); assert (OutboundPages.size() > 0); @@ -1727,7 +1726,7 @@ ConnectionDescriptor::SetCommInactivityTimeout int ConnectionDescriptor::SetCommInactivityTimeout (float value) { if (value > 0) { - InactivityTimeout = (Int64)(value * 1000000); + InactivityTimeout = (uint64_t)(value * 1000000); return 1; } return 0; @@ -1782,7 +1781,7 @@ DatagramDescriptor::SetCommInactivityTimeout int DatagramDescriptor::SetCommInactivityTimeout (float value) { if (value > 0) { - InactivityTimeout = (Int64)(value * 1000000); + InactivityTimeout = (uint64_t)(value * 1000000); return 1; } return 0; diff --git a/ext/ed.h b/ext/ed.h index 405fdcbfb..c3c2c0bb2 100644 --- a/ext/ed.h +++ b/ext/ed.h @@ -104,7 +104,7 @@ class EventableDescriptor: public Bindable_t EMCallback EventCallback; void _GenericInboundDispatch(const char*, int); - Int64 CreatedAt; + uint64_t CreatedAt; bool bCallbackUnbind; int UnbindReasonCode; EventableDescriptor *ProxyTarget; @@ -118,6 +118,7 @@ class EventableDescriptor: public Bindable_t EventMachine_t *MyEventMachine; int PendingConnectTimeout; + uint64_t LastActivity; }; @@ -235,7 +236,6 @@ class ConnectionDescriptor: public EventableDescriptor #endif bool bIsServer; - Int64 LastIo; int InactivityTimeout; private: @@ -297,7 +297,6 @@ class DatagramDescriptor: public EventableDescriptor struct sockaddr_in ReturnAddress; - Int64 LastIo; int InactivityTimeout; }; @@ -358,7 +357,6 @@ class PipeDescriptor: public EventableDescriptor protected: bool bReadAttemptedAfterClose; - Int64 LastIo; int InactivityTimeout; deque OutboundPages; @@ -391,7 +389,6 @@ class KeyboardDescriptor: public EventableDescriptor protected: bool bReadAttemptedAfterClose; - Int64 LastIo; int InactivityTimeout; private: diff --git a/ext/em.cpp b/ext/em.cpp index 48e843629..0eaceb2d4 100644 --- a/ext/em.cpp +++ b/ext/em.cpp @@ -22,17 +22,6 @@ See the file COPYING for complete licensing information. #include "project.h" -// Keep a global variable floating around -// with the current loop time as set by the Event Machine. -// This avoids the need for frequent expensive calls to time(NULL); -Int64 gCurrentLoopTime; - -#ifdef OS_WIN32 -unsigned gTickCountTickover; -unsigned gLastTickCount; -#endif - - /* The numer of max outstanding timers was once a const enum defined in em.h. * Now we define it here so that users can change its value if necessary. */ @@ -355,17 +344,17 @@ void EventMachine_t::_UpdateTime() #if defined(OS_UNIX) struct timeval tv; gettimeofday (&tv, NULL); - gCurrentLoopTime = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec)); + MyCurrentLoopTime = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)(tv.tv_usec)); #elif defined(OS_WIN32) unsigned tick = GetTickCount(); - if (tick < gLastTickCount) - gTickCountTickover += 1; - gLastTickCount = tick; - gCurrentLoopTime = ((Int64)gTickCountTickover << 32) + (Int64)tick; + if (tick < LastTickCountCount) + TickCountTickover += 1; + LastTickCountCount = tick; + MyCurrentLoopTime = ((uint64_t)TickCountTickover << 32) + (uint64_t)tick; #else - gCurrentLoopTime = (Int64)time(NULL) * 1000000LL; + MyCurrentLoopTime = (uint64_t)time(NULL) * 1000000LL; #endif } @@ -549,8 +538,8 @@ bool EventMachine_t::_RunEpollOnce() // Maybe there's a better way to do this. (Or maybe it's not that expensive after all.) // { // dispatch heartbeats - if (gCurrentLoopTime >= NextHeartbeatTime) { - NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval; + if (MyCurrentLoopTime >= NextHeartbeatTime) { + NextHeartbeatTime = MyCurrentLoopTime + HeartbeatInterval; for (int i=0; i < Descriptors.size(); i++) { EventableDescriptor *ed = Descriptors[i]; @@ -650,8 +639,8 @@ bool EventMachine_t::_RunKqueueOnce() } { // dispatch heartbeats - if (gCurrentLoopTime >= NextHeartbeatTime) { - NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval; + if (MyCurrentLoopTime >= NextHeartbeatTime) { + NextHeartbeatTime = MyCurrentLoopTime + HeartbeatInterval; for (unsigned int i=0; i < Descriptors.size(); i++) { EventableDescriptor *ed = Descriptors[i]; @@ -875,8 +864,8 @@ bool EventMachine_t::_RunSelectOnce() { // dispatch heartbeats - if (gCurrentLoopTime >= NextHeartbeatTime) { - NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval; + if (MyCurrentLoopTime >= NextHeartbeatTime) { + NextHeartbeatTime = MyCurrentLoopTime + HeartbeatInterval; for (i=0; i < Descriptors.size(); i++) { EventableDescriptor *ed = Descriptors[i]; @@ -938,10 +927,10 @@ bool EventMachine_t::_RunTimers() // one that hasn't expired yet. while (true) { - multimap::iterator i = Timers.begin(); + multimap::iterator i = Timers.begin(); if (i == Timers.end()) break; - if (i->first > gCurrentLoopTime) + if (i->first > MyCurrentLoopTime) break; if (EventCallback) (*EventCallback) (NULL, EM_TIMER_FIRED, NULL, i->second.GetBinding()); @@ -966,25 +955,25 @@ const unsigned long EventMachine_t::InstallOneshotTimer (int milliseconds) #ifdef OS_UNIX struct timeval tv; gettimeofday (&tv, NULL); - Int64 fire_at = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec)); - fire_at += ((Int64)milliseconds) * 1000LL; + uint64_t fire_at = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)(tv.tv_usec)); + fire_at += ((uint64_t)milliseconds) * 1000LL; #endif #ifdef OS_WIN32 unsigned tick = GetTickCount(); - if (tick < gLastTickCount) - gTickCountTickover += 1; - gLastTickCount = tick; + if (tick < LastTickCountCount) + TickCountTickover += 1; + LastTickCountCount = tick; - Int64 fire_at = ((Int64)gTickCountTickover << 32) + (Int64)tick; - fire_at += (Int64)milliseconds; + uint64_t fire_at = ((uint64_t)TickCountTickover << 32) + (uint64_t)tick; + fire_at += (uint64_t)milliseconds; #endif Timer_t t; #ifndef HAVE_MAKE_PAIR - multimap::iterator i = Timers.insert (multimap::value_type (fire_at, t)); + multimap::iterator i = Timers.insert (multimap::value_type (fire_at, t)); #else - multimap::iterator i = Timers.insert (make_pair (fire_at, t)); + multimap::iterator i = Timers.insert (make_pair (fire_at, t)); #endif return i->second.GetBinding(); } diff --git a/ext/em.h b/ext/em.h index 5e4f5ec41..67acabcc0 100644 --- a/ext/em.h +++ b/ext/em.h @@ -57,15 +57,6 @@ See the file COPYING for complete licensing information. #define EmSelect select #endif -#ifdef OS_UNIX -typedef long long Int64; -#endif -#ifdef OS_WIN32 -typedef __int64 Int64; -#endif - -extern Int64 gCurrentLoopTime; - class EventableDescriptor; class InotifyDescriptor; @@ -136,6 +127,8 @@ class EventMachine_t void _HandleKqueuePidEvent (struct kevent*); #endif + uint64_t GetCurrentTime() { return MyCurrentLoopTime; } + // Temporary: void _UseEpoll(); void _UseKqueue(); @@ -172,14 +165,14 @@ class EventMachine_t class Timer_t: public Bindable_t { }; - multimap Timers; + multimap Timers; map Files; map Pids; vector Descriptors; vector NewDescriptors; set ModifiedDescriptors; - Int64 NextHeartbeatTime; + uint64_t NextHeartbeatTime; int LoopBreakerReader; int LoopBreakerWriter; @@ -189,6 +182,13 @@ class EventMachine_t timeval Quantum; + uint64_t MyCurrentLoopTime; + + #ifdef OS_WIN32 + unsigned TickCountTickover; + unsigned LastTickCount; + #endif + private: bool bEpoll; int epfd; // Epoll file-descriptor diff --git a/ext/eventmachine.h b/ext/eventmachine.h index 633a320c1..ab7b5bc64 100644 --- a/ext/eventmachine.h +++ b/ext/eventmachine.h @@ -113,6 +113,7 @@ extern "C" { void evma_set_epoll (int use); void evma_set_kqueue (int use); + uint64_t evma_get_current_loop_time(); #if __cplusplus } #endif diff --git a/ext/kb.cpp b/ext/kb.cpp index 802f55010..2c17a077a 100644 --- a/ext/kb.cpp +++ b/ext/kb.cpp @@ -27,7 +27,6 @@ KeyboardDescriptor::KeyboardDescriptor KeyboardDescriptor::KeyboardDescriptor (EventMachine_t *parent_em): EventableDescriptor (0, parent_em), bReadAttemptedAfterClose (false), - LastIo (gCurrentLoopTime), InactivityTimeout (0) { #ifdef HAVE_EPOLL diff --git a/ext/pipe.cpp b/ext/pipe.cpp index 1f29783fc..09d740775 100644 --- a/ext/pipe.cpp +++ b/ext/pipe.cpp @@ -30,7 +30,6 @@ PipeDescriptor::PipeDescriptor PipeDescriptor::PipeDescriptor (int fd, pid_t subpid, EventMachine_t *parent_em): EventableDescriptor (fd, parent_em), bReadAttemptedAfterClose (false), - LastIo (gCurrentLoopTime), InactivityTimeout (0), OutboundDataSize (0), SubprocessPid (subpid) @@ -143,7 +142,7 @@ void PipeDescriptor::Read() return; } - LastIo = gCurrentLoopTime; + LastActivity = MyEventMachine->GetCurrentTime(); int total_bytes_read = 0; char readbuffer [16 * 1024]; @@ -203,7 +202,7 @@ void PipeDescriptor::Write() int sd = GetSocket(); assert (sd != INVALID_SOCKET); - LastIo = gCurrentLoopTime; + LastActivity = MyEventMachine->GetCurrentTime(); char output_buffer [16 * 1024]; size_t nbytes = 0; @@ -268,7 +267,7 @@ PipeDescriptor::Heartbeat void PipeDescriptor::Heartbeat() { // If an inactivity timeout is defined, then check for it. - if (InactivityTimeout && ((gCurrentLoopTime - LastIo) >= InactivityTimeout)) + if (InactivityTimeout && ((MyEventMachine->GetCurrentTime() - LastActivity) >= InactivityTimeout)) ScheduleClose (false); //bCloseNow = true; } diff --git a/ext/project.h b/ext/project.h index 1062a757c..a27b631bd 100644 --- a/ext/project.h +++ b/ext/project.h @@ -96,6 +96,7 @@ typedef int socklen_t; typedef int pid_t; #endif +#include using namespace std; diff --git a/ext/rubymain.cpp b/ext/rubymain.cpp index 6eb3447ac..a41649e4c 100644 --- a/ext/rubymain.cpp +++ b/ext/rubymain.cpp @@ -999,11 +999,12 @@ static VALUE t_get_loop_time (VALUE self) static ID at = rb_intern("at"); #endif - if (gCurrentLoopTime != 0) { + uint64_t current_time = evma_get_current_loop_time(); + if (current_time != 0) { #ifndef HAVE_RB_TIME_NEW - return rb_funcall(cTime, at, 2, INT2NUM(gCurrentLoopTime / 1000000), INT2NUM(gCurrentLoopTime % 1000000)); + return rb_funcall(cTime, at, 2, INT2NUM(current_time / 1000000), INT2NUM(current_time % 1000000)); #else - return rb_time_new(gCurrentLoopTime / 1000000, gCurrentLoopTime % 1000000); + return rb_time_new(current_time / 1000000, current_time % 1000000); #endif } return Qnil;