From 91d5dc38887c5ec501439f794583c7f2f3cbdea4 Mon Sep 17 00:00:00 2001 From: Jake Douglas Date: Wed, 6 May 2009 15:24:40 -0700 Subject: [PATCH] Changed to usec loop time on supported platforms. Cleaned up some unused variables. --- ext/cmain.cpp | 8 ++-- ext/ed.cpp | 78 +++++++------------------------- ext/ed.h | 31 ++++++------- ext/em.cpp | 48 ++++++++++++-------- ext/em.h | 5 +- ext/eventmachine.h | 4 +- ext/pipe.cpp | 1 - ext/rubymain.cpp | 11 ++--- lib/em/connection.rb | 6 +-- tests/test_inactivity_timeout.rb | 30 ++++++++++++ 10 files changed, 106 insertions(+), 116 deletions(-) create mode 100644 tests/test_inactivity_timeout.rb diff --git a/ext/cmain.cpp b/ext/cmain.cpp index 5e67d72a8..78e9e7597 100644 --- a/ext/cmain.cpp +++ b/ext/cmain.cpp @@ -444,22 +444,22 @@ extern "C" const char *evma__write_file (const char *filename) evma_get_comm_inactivity_timeout ********************************/ -extern "C" int evma_get_comm_inactivity_timeout (const char *binding, int *value) +extern "C" float evma_get_comm_inactivity_timeout (const char *binding) { ensure_eventmachine("evma_get_comm_inactivity_timeout"); EventableDescriptor *ed = dynamic_cast (Bindable_t::GetObject (binding)); if (ed) { - return ed->GetCommInactivityTimeout (value); + return ed->GetCommInactivityTimeout(); } else - return 0; //Perhaps this should be an exception. Access to an unknown binding. + return 0.0; //Perhaps this should be an exception. Access to an unknown binding. } /******************************** evma_set_comm_inactivity_timeout ********************************/ -extern "C" int evma_set_comm_inactivity_timeout (const char *binding, int *value) +extern "C" int evma_set_comm_inactivity_timeout (const char *binding, float value) { ensure_eventmachine("evma_set_comm_inactivity_timeout"); EventableDescriptor *ed = dynamic_cast (Bindable_t::GetObject (binding)); diff --git a/ext/ed.cpp b/ext/ed.cpp index 9024771e1..8d121675e 100644 --- a/ext/ed.cpp +++ b/ext/ed.cpp @@ -48,8 +48,6 @@ EventableDescriptor::EventableDescriptor (int sd, EventMachine_t *em): bCloseAfterWriting (false), MySocket (sd), EventCallback (NULL), - LastRead (0), - LastWritten (0), bCallbackUnbind (true), UnbindReasonCode (0), MyEventMachine (em) @@ -508,7 +506,6 @@ void ConnectionDescriptor::Read() if (r > 0) { total_bytes_read += r; - LastRead = gCurrentLoopTime; // Add a null-terminator at the the end of the buffer // that we will send to the callback. @@ -1305,7 +1302,6 @@ void DatagramDescriptor::Read() // In UDP, a zero-length packet is perfectly legal. if (r >= 0) { - LastRead = gCurrentLoopTime; // Add a null-terminator at the the end of the buffer // that we will send to the callback. @@ -1556,16 +1552,9 @@ bool ConnectionDescriptor::GetSockname (struct sockaddr *s) ConnectionDescriptor::GetCommInactivityTimeout **********************************************/ -int ConnectionDescriptor::GetCommInactivityTimeout (int *value) +float ConnectionDescriptor::GetCommInactivityTimeout() { - if (value) { - *value = InactivityTimeout; - return 1; - } - else { - // TODO, extended logging, got bad parameter. - return 0; - } + return ((float)InactivityTimeout / 1000000LL); } @@ -1573,27 +1562,13 @@ int ConnectionDescriptor::GetCommInactivityTimeout (int *value) ConnectionDescriptor::SetCommInactivityTimeout **********************************************/ -int ConnectionDescriptor::SetCommInactivityTimeout (int *value) +int ConnectionDescriptor::SetCommInactivityTimeout (float value) { - int out = 0; - - if (value) { - if ((*value==0) || (*value >= 2)) { - // Replace the value and send the old one back to the caller. - int v = *value; - *value = InactivityTimeout; - InactivityTimeout = v; - out = 1; - } - else { - // TODO, extended logging, got bad value. - } - } - else { - // TODO, extended logging, got bad parameter. + if (value > 0) { + InactivityTimeout = (Int64)(value * 1000000LL); + return 1; } - - return out; + return 0; } /******************************* @@ -1633,43 +1608,22 @@ bool DatagramDescriptor::GetSockname (struct sockaddr *s) DatagramDescriptor::GetCommInactivityTimeout ********************************************/ -int DatagramDescriptor::GetCommInactivityTimeout (int *value) +float DatagramDescriptor::GetCommInactivityTimeout() { - if (value) { - *value = InactivityTimeout; - return 1; - } - else { - // TODO, extended logging, got bad parameter. - return 0; - } + return ((float)InactivityTimeout / 1000000LL); } /******************************************** DatagramDescriptor::SetCommInactivityTimeout ********************************************/ -int DatagramDescriptor::SetCommInactivityTimeout (int *value) -{ - int out = 0; - - if (value) { - if ((*value==0) || (*value >= 2)) { - // Replace the value and send the old one back to the caller. - int v = *value; - *value = InactivityTimeout; - InactivityTimeout = v; - out = 1; - } - else { - // TODO, extended logging, got bad value. - } - } - else { - // TODO, extended logging, got bad parameter. - } - - return out; +int DatagramDescriptor::SetCommInactivityTimeout (float value) +{ + if (value > 0) { + InactivityTimeout = (Int64)(value * 1000000LL); + return 1; + } + return 0; } diff --git a/ext/ed.h b/ext/ed.h index a5fbf5207..ef16a8585 100644 --- a/ext/ed.h +++ b/ext/ed.h @@ -73,10 +73,8 @@ class EventableDescriptor: public Bindable_t virtual X509 *GetPeerCert() {return NULL;} #endif - // Properties: return 0/1 to signify T/F, and handle the values - // through arguments. - virtual int GetCommInactivityTimeout (int *value) {return 0;} - virtual int SetCommInactivityTimeout (int *value) {return 0;} + virtual float GetCommInactivityTimeout() {return 0.0;} + virtual int SetCommInactivityTimeout (float value) {return 0;} #ifdef HAVE_EPOLL struct epoll_event *GetEpollEvent() { return &EpollEvent; } @@ -96,14 +94,13 @@ class EventableDescriptor: public Bindable_t // // updating to 50 seconds, so we catch it before the OS does - PendingConnectTimeout = 50 // can easily be made an instance variable + // can easily be made an instance variable + PendingConnectTimeout = 50000000 // now in usec }; void (*EventCallback)(const char*, int, const char*, int); - - time_t CreatedAt; - time_t LastRead; - time_t LastWritten; + + Int64 CreatedAt; bool bCallbackUnbind; int UnbindReasonCode; @@ -180,8 +177,8 @@ class ConnectionDescriptor: public EventableDescriptor virtual bool GetPeername (struct sockaddr*); virtual bool GetSockname (struct sockaddr*); - virtual int GetCommInactivityTimeout (int *value); - virtual int SetCommInactivityTimeout (int *value); + virtual float GetCommInactivityTimeout(); + virtual int SetCommInactivityTimeout (float value); protected: @@ -219,7 +216,7 @@ class ConnectionDescriptor: public EventableDescriptor bool bGotExtraKqueueEvent; #endif - time_t LastIo; + Int64 LastIo; int InactivityTimeout; private: @@ -259,8 +256,8 @@ class DatagramDescriptor: public EventableDescriptor virtual bool GetPeername (struct sockaddr*); virtual bool GetSockname (struct sockaddr*); - virtual int GetCommInactivityTimeout (int *value); - virtual int SetCommInactivityTimeout (int *value); + virtual float GetCommInactivityTimeout(); + virtual int SetCommInactivityTimeout (float value); static int SendDatagram (const char*, const char*, int, const char*, int); @@ -280,7 +277,7 @@ class DatagramDescriptor: public EventableDescriptor struct sockaddr_in ReturnAddress; - time_t LastIo; + Int64 LastIo; int InactivityTimeout; }; @@ -341,7 +338,7 @@ class PipeDescriptor: public EventableDescriptor protected: bool bReadAttemptedAfterClose; - time_t LastIo; + Int64 LastIo; int InactivityTimeout; deque OutboundPages; @@ -374,7 +371,7 @@ class KeyboardDescriptor: public EventableDescriptor protected: bool bReadAttemptedAfterClose; - time_t LastIo; + Int64 LastIo; int InactivityTimeout; private: diff --git a/ext/em.cpp b/ext/em.cpp index 079d8aee3..fb63eff33 100644 --- a/ext/em.cpp +++ b/ext/em.cpp @@ -26,7 +26,7 @@ See the file COPYING for complete licensing information. // 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); -time_t gCurrentLoopTime; +Int64 gCurrentLoopTime; #ifdef OS_WIN32 unsigned gTickCountTickover; @@ -97,7 +97,7 @@ EventMachine_t::EventMachine_t (void (*event_callback)(const char*, int, const c gTerminateSignalReceived = false; // Make sure the current loop time is sane, in case we do any initializations of // objects before we start running. - gCurrentLoopTime = time(NULL); + _UpdateTime(); /* We initialize the network library here (only on Windows of course) * and initialize "loop breakers." Our destructor also does some network-level @@ -344,6 +344,32 @@ void EventMachine_t::_InitializeLoopBreaker() #endif } +/*************************** +EventMachine_t::_UpdateTime +***************************/ + +void EventMachine_t::_UpdateTime() +{ + #ifdef OS_UNIX + struct timeval tv; + gettimeofday (&tv, NULL); + gCurrentLoopTime = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec)); + #endif + + #ifdef OS_WIN32 + unsigned tick = GetTickCount(); + if (tick < gLastTickCount) + gTickCountTickover += 1; + gLastTickCount = tick; + gCurrentLoopTime = ((Int64)gTickCountTickover << 32) + (Int64)tick; + #endif + + #ifndef OS_UNIX + #ifndef OS_WIN32 + gCurrentLoopTime = (Int64)time(NULL) * 1000000LL; + #endif + #endif +} /******************* EventMachine_t::Run @@ -393,7 +419,7 @@ void EventMachine_t::Run() #endif while (true) { - gCurrentLoopTime = time(NULL); + _UpdateTime(); if (!_RunTimers()) break; @@ -893,25 +919,11 @@ bool EventMachine_t::_RunTimers() // Just keep inspecting and processing the list head until we hit // one that hasn't expired yet. - #ifdef OS_UNIX - struct timeval tv; - gettimeofday (&tv, NULL); - Int64 now = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec)); - #endif - - #ifdef OS_WIN32 - unsigned tick = GetTickCount(); - if (tick < gLastTickCount) - gTickCountTickover += 1; - gLastTickCount = tick; - Int64 now = ((Int64)gTickCountTickover << 32) + (Int64)tick; - #endif - while (true) { multimap::iterator i = Timers.begin(); if (i == Timers.end()) break; - if (i->first > now) + if (i->first > gCurrentLoopTime) break; if (EventCallback) (*EventCallback) ("", EM_TIMER_FIRED, i->second.GetBinding().c_str(), i->second.GetBinding().length()); diff --git a/ext/em.h b/ext/em.h index cb465f382..9b4c70bb1 100644 --- a/ext/em.h +++ b/ext/em.h @@ -57,7 +57,7 @@ typedef long long Int64; typedef __int64 Int64; #endif -extern time_t gCurrentLoopTime; +extern Int64 gCurrentLoopTime; class EventableDescriptor; class InotifyDescriptor; @@ -137,6 +137,7 @@ class EventMachine_t private: bool _RunOnce(); bool _RunTimers(); + void _UpdateTime(); void _AddNewDescriptors(); void _ModifyDescriptors(); void _InitializeLoopBreaker(); @@ -169,7 +170,7 @@ class EventMachine_t vector NewDescriptors; set ModifiedDescriptors; - time_t NextHeartbeatTime; + Int64 NextHeartbeatTime; int LoopBreakerReader; int LoopBreakerWriter; diff --git a/ext/eventmachine.h b/ext/eventmachine.h index 95ccdf8a8..43a37859e 100644 --- a/ext/eventmachine.h +++ b/ext/eventmachine.h @@ -68,8 +68,8 @@ extern "C" { int evma_get_connection_count(); int evma_send_data_to_connection (const char *binding, const char *data, int data_length); int evma_send_datagram (const char *binding, const char *data, int data_length, const char *address, int port); - int evma_get_comm_inactivity_timeout (const char *binding, /*out*/int *value); - int evma_set_comm_inactivity_timeout (const char *binding, /*in,out*/int *value); + float evma_get_comm_inactivity_timeout (const char *binding); + int evma_set_comm_inactivity_timeout (const char *binding, float value); int evma_get_outbound_data_size (const char *binding); int evma_send_file_data_to_connection (const char *binding, const char *filename); diff --git a/ext/pipe.cpp b/ext/pipe.cpp index 5f8910077..e53e8a693 100644 --- a/ext/pipe.cpp +++ b/ext/pipe.cpp @@ -164,7 +164,6 @@ void PipeDescriptor::Read() if (r > 0) { total_bytes_read += r; - LastRead = gCurrentLoopTime; // Add a null-terminator at the the end of the buffer // that we will send to the callback. diff --git a/ext/rubymain.cpp b/ext/rubymain.cpp index a9558e470..c8fd2819b 100644 --- a/ext/rubymain.cpp +++ b/ext/rubymain.cpp @@ -368,10 +368,7 @@ t_get_comm_inactivity_timeout static VALUE t_get_comm_inactivity_timeout (VALUE self, VALUE signature) { - int timeout; - if (evma_get_comm_inactivity_timeout (StringValuePtr (signature), &timeout)) - return INT2FIX (timeout); - return Qnil; + return rb_float_new(evma_get_comm_inactivity_timeout(StringValuePtr(signature))); } /***************************** @@ -380,10 +377,10 @@ t_set_comm_inactivity_timeout static VALUE t_set_comm_inactivity_timeout (VALUE self, VALUE signature, VALUE timeout) { - int ti = FIX2INT (timeout); - if (evma_set_comm_inactivity_timeout (StringValuePtr (signature), &ti)); + float ti = RFLOAT(timeout)->value; + if (evma_set_comm_inactivity_timeout (StringValuePtr (signature), ti)); return Qtrue; - return Qnil; + return Qfalse; } diff --git a/lib/em/connection.rb b/lib/em/connection.rb index 5b6a1639c..6b40db6f0 100644 --- a/lib/em/connection.rb +++ b/lib/em/connection.rb @@ -421,7 +421,7 @@ def get_status EventMachine::get_subprocess_status @signature end - # comm_inactivity_timeout returns the current value (in seconds) of the inactivity-timeout + # comm_inactivity_timeout returns the current value (float in seconds) of the inactivity-timeout # property of network-connection and datagram-socket objects. A nonzero value # indicates that the connection or socket will automatically be closed if no read or write # activity takes place for at least that number of seconds. @@ -436,13 +436,13 @@ def comm_inactivity_timeout= value end # comm_inactivity_timeout= allows you to set the inactivity-timeout property for - # a network connection or datagram socket. Specify a non-negative numeric value in seconds. + # a network connection or datagram socket. Specify a non-negative float value in seconds. # If the value is greater than zero, the connection or socket will automatically be closed # if no read or write activity takes place for at least that number of seconds. # Specify a value of zero to indicate that no automatic timeout should take place. # Zero is the default value. def set_comm_inactivity_timeout value - EventMachine::set_comm_inactivity_timeout @signature, value + EventMachine::set_comm_inactivity_timeout @signature, value.to_f end # Reconnect to a given host/port with the current EventMachine::Connection instance diff --git a/tests/test_inactivity_timeout.rb b/tests/test_inactivity_timeout.rb new file mode 100644 index 000000000..545abab8e --- /dev/null +++ b/tests/test_inactivity_timeout.rb @@ -0,0 +1,30 @@ +$:.unshift "../lib" +require 'eventmachine' +require 'test/unit' + +class TestInactivityTimeout < Test::Unit::TestCase + + def test_default + $timeout = nil + EM.run { + c = EM.connect("127.0.0.1", 54321) + $timeout = c.comm_inactivity_timeout + EM.stop + } + + assert_equal(0.0, $timeout) + end + + def test_with_set + $timeout = nil + EM.run { + c = EM.connect("127.0.0.1", 54321) + c.comm_inactivity_timeout = 2.5 + $timeout = c.comm_inactivity_timeout + EM.stop + } + + assert_equal(2.5, $timeout) + end + +end