smparkes-eventmachine 0.12.10.2 → 0.12.10.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/ed.h CHANGED
@@ -75,10 +75,10 @@ class EventableDescriptor: public Bindable_t
75
75
  virtual X509 *GetPeerCert() {return NULL;}
76
76
  #endif
77
77
 
78
- virtual float GetCommInactivityTimeout() {return 0.0;}
79
- virtual int SetCommInactivityTimeout (float value) {return 0;}
80
- float GetPendingConnectTimeout();
81
- int SetPendingConnectTimeout (float value);
78
+ virtual uint64_t GetCommInactivityTimeout() {return 0;}
79
+ virtual int SetCommInactivityTimeout (uint64_t value) {return 0;}
80
+ uint64_t GetPendingConnectTimeout();
81
+ int SetPendingConnectTimeout (uint64_t value);
82
82
 
83
83
  #ifdef HAVE_EPOLL
84
84
  struct epoll_event *GetEpollEvent() { return &EpollEvent; }
@@ -92,6 +92,10 @@ class EventableDescriptor: public Bindable_t
92
92
  virtual bool Pause(){ return false; }
93
93
  virtual bool Resume(){ return false; }
94
94
 
95
+ virtual int ReportErrorStatus(){ return 0; }
96
+ virtual bool IsConnectPending(){ return false; }
97
+ virtual uint64_t GetNextHeartbeat();
98
+
95
99
  private:
96
100
  bool bCloseNow;
97
101
  bool bCloseAfterWriting;
@@ -102,7 +106,7 @@ class EventableDescriptor: public Bindable_t
102
106
  EMCallback EventCallback;
103
107
  void _GenericInboundDispatch(const char*, int);
104
108
 
105
- Int64 CreatedAt;
109
+ uint64_t CreatedAt;
106
110
  bool bCallbackUnbind;
107
111
  int UnbindReasonCode;
108
112
  EventableDescriptor *ProxyTarget;
@@ -115,7 +119,10 @@ class EventableDescriptor: public Bindable_t
115
119
  #endif
116
120
 
117
121
  EventMachine_t *MyEventMachine;
118
- int PendingConnectTimeout;
122
+ uint64_t PendingConnectTimeout;
123
+ uint64_t InactivityTimeout;
124
+ uint64_t LastActivity;
125
+ uint64_t NextHeartbeat;
119
126
  };
120
127
 
121
128
 
@@ -149,10 +156,6 @@ class ConnectionDescriptor: public EventableDescriptor
149
156
  ConnectionDescriptor (int, EventMachine_t*);
150
157
  virtual ~ConnectionDescriptor();
151
158
 
152
- static int SendDataToConnection (const unsigned long, const char*, int);
153
- static void CloseConnection (const unsigned long, bool);
154
- static int ReportErrorStatus (const unsigned long);
155
-
156
159
  int SendOutboundData (const char*, int);
157
160
 
158
161
  void SetConnectPending (bool f);
@@ -195,9 +198,11 @@ class ConnectionDescriptor: public EventableDescriptor
195
198
  virtual bool GetPeername (struct sockaddr*);
196
199
  virtual bool GetSockname (struct sockaddr*);
197
200
 
198
- virtual float GetCommInactivityTimeout();
199
- virtual int SetCommInactivityTimeout (float value);
201
+ virtual uint64_t GetCommInactivityTimeout();
202
+ virtual int SetCommInactivityTimeout (uint64_t value);
200
203
 
204
+ virtual int ReportErrorStatus();
205
+ virtual bool IsConnectPending(){ return bConnectPending; }
201
206
 
202
207
  protected:
203
208
  struct OutboundPage {
@@ -236,8 +241,6 @@ class ConnectionDescriptor: public EventableDescriptor
236
241
  #endif
237
242
 
238
243
  bool bIsServer;
239
- Int64 LastIo;
240
- int InactivityTimeout;
241
244
 
242
245
  private:
243
246
  void _UpdateEvents();
@@ -246,7 +249,6 @@ class ConnectionDescriptor: public EventableDescriptor
246
249
  void _DispatchInboundData (const char *buffer, int size);
247
250
  void _DispatchCiphertext();
248
251
  int _SendRawOutboundData (const char*, int);
249
- int _ReportErrorStatus();
250
252
  void _CheckHandshakeStatus();
251
253
 
252
254
  };
@@ -278,11 +280,8 @@ class DatagramDescriptor: public EventableDescriptor
278
280
  virtual bool GetPeername (struct sockaddr*);
279
281
  virtual bool GetSockname (struct sockaddr*);
280
282
 
281
- virtual float GetCommInactivityTimeout();
282
- virtual int SetCommInactivityTimeout (float value);
283
-
284
- static int SendDatagram (const unsigned long, const char*, int, const char*, int);
285
-
283
+ virtual uint64_t GetCommInactivityTimeout();
284
+ virtual int SetCommInactivityTimeout (uint64_t value);
286
285
 
287
286
  protected:
288
287
  struct OutboundPage {
@@ -298,9 +297,6 @@ class DatagramDescriptor: public EventableDescriptor
298
297
  int OutboundDataSize;
299
298
 
300
299
  struct sockaddr_in ReturnAddress;
301
-
302
- Int64 LastIo;
303
- int InactivityTimeout;
304
300
  };
305
301
 
306
302
 
@@ -360,8 +356,6 @@ class PipeDescriptor: public EventableDescriptor
360
356
 
361
357
  protected:
362
358
  bool bReadAttemptedAfterClose;
363
- Int64 LastIo;
364
- int InactivityTimeout;
365
359
 
366
360
  deque<OutboundPage> OutboundPages;
367
361
  int OutboundDataSize;
@@ -393,8 +387,6 @@ class KeyboardDescriptor: public EventableDescriptor
393
387
 
394
388
  protected:
395
389
  bool bReadAttemptedAfterClose;
396
- Int64 LastIo;
397
- int InactivityTimeout;
398
390
 
399
391
  private:
400
392
  void _DispatchInboundData (const char *buffer, int size);
data/ext/em.cpp CHANGED
@@ -22,17 +22,6 @@ See the file COPYING for complete licensing information.
22
22
 
23
23
  #include "project.h"
24
24
 
25
- // Keep a global variable floating around
26
- // with the current loop time as set by the Event Machine.
27
- // This avoids the need for frequent expensive calls to time(NULL);
28
- Int64 gCurrentLoopTime;
29
-
30
- #ifdef OS_WIN32
31
- unsigned gTickCountTickover;
32
- unsigned gLastTickCount;
33
- #endif
34
-
35
-
36
25
  /* The numer of max outstanding timers was once a const enum defined in em.h.
37
26
  * Now we define it here so that users can change its value if necessary.
38
27
  */
@@ -353,21 +342,76 @@ EventMachine_t::_UpdateTime
353
342
 
354
343
  void EventMachine_t::_UpdateTime()
355
344
  {
345
+ MyCurrentLoopTime = GetRealTime();
346
+ }
347
+
348
+ /***************************
349
+ EventMachine_t::GetRealTime
350
+ ***************************/
351
+
352
+ uint64_t EventMachine_t::GetRealTime()
353
+ {
354
+ uint64_t current_time;
356
355
  #if defined(OS_UNIX)
357
356
  struct timeval tv;
358
357
  gettimeofday (&tv, NULL);
359
- gCurrentLoopTime = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec));
358
+ current_time = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)(tv.tv_usec));
360
359
 
361
360
  #elif defined(OS_WIN32)
362
361
  unsigned tick = GetTickCount();
363
- if (tick < gLastTickCount)
364
- gTickCountTickover += 1;
365
- gLastTickCount = tick;
366
- gCurrentLoopTime = ((Int64)gTickCountTickover << 32) + (Int64)tick;
362
+ if (tick < LastTickCountCount)
363
+ TickCountTickover += 1;
364
+ LastTickCountCount = tick;
365
+ current_time = ((uint64_t)TickCountTickover << 32) + (uint64_t)tick;
367
366
 
368
367
  #else
369
- gCurrentLoopTime = (Int64)time(NULL) * 1000000LL;
368
+ current_time = (uint64_t)time(NULL) * 1000000LL;
370
369
  #endif
370
+ return current_time;
371
+ }
372
+
373
+ /***********************************
374
+ EventMachine_t::_DispatchHeartbeats
375
+ ***********************************/
376
+
377
+ void EventMachine_t::_DispatchHeartbeats()
378
+ {
379
+ while (true) {
380
+ multimap<uint64_t,EventableDescriptor*>::iterator i = Heartbeats.begin();
381
+ if (i == Heartbeats.end())
382
+ break;
383
+ if (i->first > MyCurrentLoopTime)
384
+ break;
385
+ EventableDescriptor *ed = i->second;
386
+ ed->Heartbeat();
387
+ QueueHeartbeat(ed);
388
+ }
389
+ }
390
+
391
+ /******************************
392
+ EventMachine_t::QueueHeartbeat
393
+ ******************************/
394
+
395
+ void EventMachine_t::QueueHeartbeat(EventableDescriptor *ed)
396
+ {
397
+ uint64_t heartbeat = ed->GetNextHeartbeat();
398
+
399
+ if (heartbeat) {
400
+ #ifndef HAVE_MAKE_PAIR
401
+ Heartbeats.insert (multimap<uint64_t,EventableDescriptor*>::value_type (heartbeat, ed));
402
+ #else
403
+ Heartbeats.insert (make_pair (heartbeat, ed));
404
+ #endif
405
+ }
406
+ }
407
+
408
+ /******************************
409
+ EventMachine_t::ClearHeartbeat
410
+ ******************************/
411
+
412
+ void EventMachine_t::ClearHeartbeat(uint64_t key)
413
+ {
414
+ Heartbeats.erase(key);
371
415
  }
372
416
 
373
417
  /*******************
@@ -447,12 +491,16 @@ EventMachine_t::_RunOnce
447
491
 
448
492
  bool EventMachine_t::_RunOnce()
449
493
  {
494
+ bool ret;
450
495
  if (bEpoll)
451
- return _RunEpollOnce();
496
+ ret = _RunEpollOnce();
452
497
  else if (bKqueue)
453
- return _RunKqueueOnce();
498
+ ret = _RunKqueueOnce();
454
499
  else
455
- return _RunSelectOnce();
500
+ ret = _RunSelectOnce();
501
+ _DispatchHeartbeats();
502
+ _CleanupSockets();
503
+ return ret;
456
504
  }
457
505
 
458
506
 
@@ -467,12 +515,28 @@ bool EventMachine_t::_RunEpollOnce()
467
515
  assert (epfd != -1);
468
516
  int s;
469
517
 
518
+ timeval tv = _TimeTilNextEvent();
519
+
470
520
  #ifdef BUILD_FOR_RUBY
521
+ int ret = 0;
522
+ fd_set fdreads;
523
+
524
+ FD_ZERO(&fdreads);
525
+ FD_SET(epfd, &fdreads);
526
+
527
+ while ((ret = rb_thread_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
528
+ if (ret == -1) continue;
529
+ if (ret == 0) return true;
530
+ }
531
+
471
532
  TRAP_BEG;
472
- #endif
473
- s = epoll_wait (epfd, epoll_events, MaxEvents, 50);
474
- #ifdef BUILD_FOR_RUBY
533
+ s = epoll_wait (epfd, epoll_events, MaxEvents, 0);
475
534
  TRAP_END;
535
+ #else
536
+ int duration = 0;
537
+ duration = duration + (tv.tv_sec * 1000);
538
+ duration = duration + (tv.tv_usec / 1000);
539
+ s = epoll_wait (epfd, epoll_events, MaxEvents, duration);
476
540
  #endif
477
541
 
478
542
  if (s > 0) {
@@ -501,72 +565,6 @@ bool EventMachine_t::_RunEpollOnce()
501
565
  EmSelect (0, NULL, NULL, NULL, &tv);
502
566
  }
503
567
 
504
- { // cleanup dying sockets
505
- // vector::pop_back works in constant time.
506
- // TODO, rip this out and only delete the descriptors we know have died,
507
- // rather than traversing the whole list.
508
- // Modified 05Jan08 per suggestions by Chris Heath. It's possible that
509
- // an EventableDescriptor will have a descriptor value of -1. That will
510
- // happen if EventableDescriptor::Close was called on it. In that case,
511
- // don't call epoll_ctl to remove the socket's filters from the epoll set.
512
- // According to the epoll docs, this happens automatically when the
513
- // descriptor is closed anyway. This is different from the case where
514
- // the socket has already been closed but the descriptor in the ED object
515
- // hasn't yet been set to INVALID_SOCKET.
516
- int i, j;
517
- int nSockets = Descriptors.size();
518
- for (i=0, j=0; i < nSockets; i++) {
519
- EventableDescriptor *ed = Descriptors[i];
520
- assert (ed);
521
- if (ed->ShouldDelete()) {
522
- if (ed->GetSocket() != INVALID_SOCKET) {
523
- assert (bEpoll); // wouldn't be in this method otherwise.
524
- assert (epfd != -1);
525
- int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
526
- // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
527
- if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
528
- char buf [200];
529
- snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
530
- throw std::runtime_error (buf);
531
- }
532
- }
533
-
534
- ModifiedDescriptors.erase (ed);
535
- delete ed;
536
- }
537
- else
538
- Descriptors [j++] = ed;
539
- }
540
- while ((size_t)j < Descriptors.size())
541
- Descriptors.pop_back();
542
-
543
- }
544
-
545
- // TODO, heartbeats.
546
- // Added 14Sep07, its absence was noted by Brian Candler. But the comment was here, indicated
547
- // that this got thought about and not done when EPOLL was originally written. Was there a reason
548
- // not to do it, or was it an oversight? Certainly, running a heartbeat on 50,000 connections every
549
- // two seconds can get to be a real bear, especially if all we're doing is timing out dead ones.
550
- // Maybe there's a better way to do this. (Or maybe it's not that expensive after all.)
551
- //
552
- { // dispatch heartbeats
553
- if (gCurrentLoopTime >= NextHeartbeatTime) {
554
- NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval;
555
-
556
- for (int i=0; i < Descriptors.size(); i++) {
557
- EventableDescriptor *ed = Descriptors[i];
558
- assert (ed);
559
- ed->Heartbeat();
560
- }
561
- }
562
- }
563
-
564
- #ifdef BUILD_FOR_RUBY
565
- if (!rb_thread_alone()) {
566
- rb_thread_schedule();
567
- }
568
- #endif
569
-
570
568
  return true;
571
569
  #else
572
570
  throw std::runtime_error ("epoll is not implemented on this platform");
@@ -582,15 +580,30 @@ bool EventMachine_t::_RunKqueueOnce()
582
580
  {
583
581
  #ifdef HAVE_KQUEUE
584
582
  assert (kqfd != -1);
585
- struct timespec ts = {0, 10000000}; // Too frequent. Use blocking_region
586
-
587
583
  int k;
584
+
585
+ timeval tv = _TimeTilNextEvent();
586
+
588
587
  #ifdef BUILD_FOR_RUBY
588
+ int ret = 0;
589
+ fd_set fdreads;
590
+
591
+ FD_ZERO(&fdreads);
592
+ FD_SET(kqfd, &fdreads);
593
+
594
+ while ((ret = rb_thread_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
595
+ if (ret == -1) continue;
596
+ if (ret == 0) return true;
597
+ }
598
+
589
599
  TRAP_BEG;
590
- #endif
591
- k = kevent (kqfd, NULL, 0, Karray, MaxEvents, &ts);
592
- #ifdef BUILD_FOR_RUBY
600
+ k = kevent (kqfd, NULL, 0, Karray, MaxEvents, NULL);
593
601
  TRAP_END;
602
+ #else
603
+ struct timespec ts;
604
+ ts.tv_sec = tv.tv_sec;
605
+ ts.tv_nsec = tv.tv_usec * 1000;
606
+ k = kevent (kqfd, NULL, 0, Karray, MaxEvents, &ts);
594
607
  #endif
595
608
 
596
609
  struct kevent *ke = Karray;
@@ -627,42 +640,6 @@ bool EventMachine_t::_RunKqueueOnce()
627
640
  ++ke;
628
641
  }
629
642
 
630
- { // cleanup dying sockets
631
- // vector::pop_back works in constant time.
632
- // TODO, rip this out and only delete the descriptors we know have died,
633
- // rather than traversing the whole list.
634
- // In kqueue, closing a descriptor automatically removes its event filters.
635
-
636
- int i, j;
637
- int nSockets = Descriptors.size();
638
- for (i=0, j=0; i < nSockets; i++) {
639
- EventableDescriptor *ed = Descriptors[i];
640
- assert (ed);
641
- if (ed->ShouldDelete()) {
642
- ModifiedDescriptors.erase (ed);
643
- delete ed;
644
- }
645
- else
646
- Descriptors [j++] = ed;
647
- }
648
- while ((size_t)j < Descriptors.size())
649
- Descriptors.pop_back();
650
-
651
- }
652
-
653
- { // dispatch heartbeats
654
- if (gCurrentLoopTime >= NextHeartbeatTime) {
655
- NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval;
656
-
657
- for (unsigned int i=0; i < Descriptors.size(); i++) {
658
- EventableDescriptor *ed = Descriptors[i];
659
- assert (ed);
660
- ed->Heartbeat();
661
- }
662
- }
663
- }
664
-
665
-
666
643
  // TODO, replace this with rb_thread_blocking_region for 1.9 builds.
667
644
  #ifdef BUILD_FOR_RUBY
668
645
  if (!rb_thread_alone()) {
@@ -677,6 +654,85 @@ bool EventMachine_t::_RunKqueueOnce()
677
654
  }
678
655
 
679
656
 
657
+ /*********************************
658
+ EventMachine_t::_TimeTilNextEvent
659
+ *********************************/
660
+
661
+ timeval EventMachine_t::_TimeTilNextEvent()
662
+ {
663
+ uint64_t next_event = 0;
664
+
665
+ if (!Heartbeats.empty()) {
666
+ multimap<uint64_t,EventableDescriptor*>::iterator heartbeats = Heartbeats.begin();
667
+ next_event = heartbeats->first;
668
+ }
669
+
670
+ if (!Timers.empty()) {
671
+ multimap<uint64_t,Timer_t>::iterator timers = Timers.begin();
672
+ if (timers->first != 0 && timers->first < next_event)
673
+ next_event = timers->first;
674
+ }
675
+
676
+ timeval tv;
677
+
678
+ if (next_event == 0) {
679
+ tv = Quantum;
680
+ } else {
681
+ uint64_t duration = next_event - MyCurrentLoopTime;
682
+ tv.tv_sec = duration / 1000000;
683
+ tv.tv_usec = duration % 1000000;
684
+ }
685
+
686
+ return tv;
687
+ }
688
+
689
+ /*******************************
690
+ EventMachine_t::_CleanupSockets
691
+ *******************************/
692
+
693
+ void EventMachine_t::_CleanupSockets()
694
+ {
695
+ // TODO, rip this out and only delete the descriptors we know have died,
696
+ // rather than traversing the whole list.
697
+ // Modified 05Jan08 per suggestions by Chris Heath. It's possible that
698
+ // an EventableDescriptor will have a descriptor value of -1. That will
699
+ // happen if EventableDescriptor::Close was called on it. In that case,
700
+ // don't call epoll_ctl to remove the socket's filters from the epoll set.
701
+ // According to the epoll docs, this happens automatically when the
702
+ // descriptor is closed anyway. This is different from the case where
703
+ // the socket has already been closed but the descriptor in the ED object
704
+ // hasn't yet been set to INVALID_SOCKET.
705
+ // In kqueue, closing a descriptor automatically removes its event filters.
706
+ int i, j;
707
+ int nSockets = Descriptors.size();
708
+ for (i=0, j=0; i < nSockets; i++) {
709
+ EventableDescriptor *ed = Descriptors[i];
710
+ assert (ed);
711
+ if (ed->ShouldDelete()) {
712
+ #ifdef HAVE_EPOLL
713
+ if (bEpoll) {
714
+ assert (epfd != -1);
715
+ if (ed->GetSocket() != INVALID_SOCKET) {
716
+ int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
717
+ // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
718
+ if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
719
+ char buf [200];
720
+ snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
721
+ throw std::runtime_error (buf);
722
+ }
723
+ }
724
+ ModifiedDescriptors.erase(ed);
725
+ }
726
+ #endif
727
+ delete ed;
728
+ }
729
+ else
730
+ Descriptors [j++] = ed;
731
+ }
732
+ while ((size_t)j < Descriptors.size())
733
+ Descriptors.pop_back();
734
+ }
735
+
680
736
  /*********************************
681
737
  EventMachine_t::_ModifyEpollEvent
682
738
  *********************************/
@@ -829,7 +885,7 @@ bool EventMachine_t::_RunSelectOnce()
829
885
  { // read and write the sockets
830
886
  //timeval tv = {1, 0}; // Solaris fails if the microseconds member is >= 1000000.
831
887
  //timeval tv = Quantum;
832
- SelectData.tv = Quantum;
888
+ SelectData.tv = _TimeTilNextEvent();
833
889
  int s = SelectData._Select();
834
890
  //rb_thread_blocking_region(xxx,(void*)&SelectData,RUBY_UBF_IO,0);
835
891
  //int s = EmSelect (SelectData.maxsocket+1, &(SelectData.fdreads), &(SelectData.fdwrites), NULL, &(SelectData.tv));
@@ -874,36 +930,6 @@ bool EventMachine_t::_RunSelectOnce()
874
930
  }
875
931
  }
876
932
 
877
-
878
- { // dispatch heartbeats
879
- if (gCurrentLoopTime >= NextHeartbeatTime) {
880
- NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval;
881
-
882
- for (i=0; i < Descriptors.size(); i++) {
883
- EventableDescriptor *ed = Descriptors[i];
884
- assert (ed);
885
- ed->Heartbeat();
886
- }
887
- }
888
- }
889
-
890
- { // cleanup dying sockets
891
- // vector::pop_back works in constant time.
892
- int i, j;
893
- int nSockets = Descriptors.size();
894
- for (i=0, j=0; i < nSockets; i++) {
895
- EventableDescriptor *ed = Descriptors[i];
896
- assert (ed);
897
- if (ed->ShouldDelete())
898
- delete ed;
899
- else
900
- Descriptors [j++] = ed;
901
- }
902
- while ((size_t)j < Descriptors.size())
903
- Descriptors.pop_back();
904
-
905
- }
906
-
907
933
  return true;
908
934
  }
909
935
 
@@ -921,7 +947,7 @@ void EventMachine_t::_ReadLoopBreaker()
921
947
  char buffer [1024];
922
948
  read (LoopBreakerReader, buffer, sizeof(buffer));
923
949
  if (EventCallback)
924
- (*EventCallback)(NULL, EM_LOOPBREAK_SIGNAL, "", 0);
950
+ (*EventCallback)(0, EM_LOOPBREAK_SIGNAL, "", 0);
925
951
  }
926
952
 
927
953
 
@@ -939,13 +965,13 @@ bool EventMachine_t::_RunTimers()
939
965
  // one that hasn't expired yet.
940
966
 
941
967
  while (true) {
942
- multimap<Int64,Timer_t>::iterator i = Timers.begin();
968
+ multimap<uint64_t,Timer_t>::iterator i = Timers.begin();
943
969
  if (i == Timers.end())
944
970
  break;
945
- if (i->first > gCurrentLoopTime)
971
+ if (i->first > MyCurrentLoopTime)
946
972
  break;
947
973
  if (EventCallback)
948
- (*EventCallback) (NULL, EM_TIMER_FIRED, NULL, i->second.GetBinding());
974
+ (*EventCallback) (0, EM_TIMER_FIRED, NULL, i->second.GetBinding());
949
975
  Timers.erase (i);
950
976
  }
951
977
  return true;
@@ -964,28 +990,31 @@ const unsigned long EventMachine_t::InstallOneshotTimer (int milliseconds)
964
990
  // Don't use the global loop-time variable here, because we might
965
991
  // get called before the main event machine is running.
966
992
 
993
+ // XXX This should be replaced with a call to _GetRealTime(), but I don't
994
+ // understand if this is a bug or not? For OS_UNIX we multiply the argument
995
+ // milliseconds by 1000, but for OS_WIN32 we do not? This needs to be sorted out.
967
996
  #ifdef OS_UNIX
968
997
  struct timeval tv;
969
998
  gettimeofday (&tv, NULL);
970
- Int64 fire_at = (((Int64)(tv.tv_sec)) * 1000000LL) + ((Int64)(tv.tv_usec));
971
- fire_at += ((Int64)milliseconds) * 1000LL;
999
+ uint64_t fire_at = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)(tv.tv_usec));
1000
+ fire_at += ((uint64_t)milliseconds) * 1000LL;
972
1001
  #endif
973
1002
 
974
1003
  #ifdef OS_WIN32
975
1004
  unsigned tick = GetTickCount();
976
- if (tick < gLastTickCount)
977
- gTickCountTickover += 1;
978
- gLastTickCount = tick;
1005
+ if (tick < LastTickCountCount)
1006
+ TickCountTickover += 1;
1007
+ LastTickCountCount = tick;
979
1008
 
980
- Int64 fire_at = ((Int64)gTickCountTickover << 32) + (Int64)tick;
981
- fire_at += (Int64)milliseconds;
1009
+ uint64_t fire_at = ((uint64_t)TickCountTickover << 32) + (uint64_t)tick;
1010
+ fire_at += (uint64_t)milliseconds;
982
1011
  #endif
983
1012
 
984
1013
  Timer_t t;
985
1014
  #ifndef HAVE_MAKE_PAIR
986
- multimap<Int64,Timer_t>::iterator i = Timers.insert (multimap<Int64,Timer_t>::value_type (fire_at, t));
1015
+ multimap<uint64_t,Timer_t>::iterator i = Timers.insert (multimap<uint64_t,Timer_t>::value_type (fire_at, t));
987
1016
  #else
988
- multimap<Int64,Timer_t>::iterator i = Timers.insert (make_pair (fire_at, t));
1017
+ multimap<uint64_t,Timer_t>::iterator i = Timers.insert (make_pair (fire_at, t));
989
1018
  #endif
990
1019
  return i->second.GetBinding();
991
1020
  }
@@ -1086,7 +1115,7 @@ const unsigned long EventMachine_t::ConnectToServer (const char *bind_addr, int
1086
1115
  }
1087
1116
  }
1088
1117
 
1089
- unsigned long out = NULL;
1118
+ unsigned long out = 0;
1090
1119
 
1091
1120
  #ifdef OS_UNIX
1092
1121
  //if (connect (sd, (sockaddr*)&pin, sizeof pin) == 0) {
@@ -1215,10 +1244,10 @@ const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
1215
1244
  // The whole rest of this function is only compiled on Unix systems.
1216
1245
  #ifdef OS_UNIX
1217
1246
 
1218
- unsigned long out = NULL;
1247
+ unsigned long out = 0;
1219
1248
 
1220
1249
  if (!server || !*server)
1221
- return NULL;
1250
+ return 0;
1222
1251
 
1223
1252
  sockaddr_un pun;
1224
1253
  memset (&pun, 0, sizeof(pun));
@@ -1234,19 +1263,19 @@ const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
1234
1263
 
1235
1264
  int fd = socket (AF_LOCAL, SOCK_STREAM, 0);
1236
1265
  if (fd == INVALID_SOCKET)
1237
- return NULL;
1266
+ return 0;
1238
1267
 
1239
1268
  // From here on, ALL error returns must close the socket.
1240
1269
  // NOTE: At this point, the socket is still a blocking socket.
1241
1270
  if (connect (fd, (struct sockaddr*)&pun, sizeof(pun)) != 0) {
1242
1271
  closesocket (fd);
1243
- return NULL;
1272
+ return 0;
1244
1273
  }
1245
1274
 
1246
1275
  // Set the newly-connected socket nonblocking.
1247
1276
  if (!SetSocketNonblocking (fd)) {
1248
1277
  closesocket (fd);
1249
- return NULL;
1278
+ return 0;
1250
1279
  }
1251
1280
 
1252
1281
  // Set up a connection descriptor and add it to the event-machine.
@@ -1450,9 +1479,9 @@ const unsigned long EventMachine_t::CreateTcpServer (const char *server, int por
1450
1479
  int family, bind_size;
1451
1480
  struct sockaddr *bind_here = name2address (server, port, &family, &bind_size);
1452
1481
  if (!bind_here)
1453
- return NULL;
1482
+ return 0;
1454
1483
 
1455
- unsigned long output_binding = NULL;
1484
+ unsigned long output_binding = 0;
1456
1485
 
1457
1486
  //struct sockaddr_in sin;
1458
1487
 
@@ -1532,7 +1561,7 @@ const unsigned long EventMachine_t::CreateTcpServer (const char *server, int por
1532
1561
  fail:
1533
1562
  if (sd_accept != INVALID_SOCKET)
1534
1563
  closesocket (sd_accept);
1535
- return NULL;
1564
+ return 0;
1536
1565
  }
1537
1566
 
1538
1567
 
@@ -1542,7 +1571,7 @@ EventMachine_t::OpenDatagramSocket
1542
1571
 
1543
1572
  const unsigned long EventMachine_t::OpenDatagramSocket (const char *address, int port)
1544
1573
  {
1545
- unsigned long output_binding = NULL;
1574
+ unsigned long output_binding = 0;
1546
1575
 
1547
1576
  int sd = socket (AF_INET, SOCK_DGRAM, 0);
1548
1577
  if (sd == INVALID_SOCKET)
@@ -1593,7 +1622,7 @@ const unsigned long EventMachine_t::OpenDatagramSocket (const char *address, int
1593
1622
  fail:
1594
1623
  if (sd != INVALID_SOCKET)
1595
1624
  closesocket (sd);
1596
- return NULL;
1625
+ return 0;
1597
1626
  }
1598
1627
 
1599
1628
 
@@ -1702,6 +1731,7 @@ void EventMachine_t::_AddNewDescriptors()
1702
1731
  */
1703
1732
  #endif
1704
1733
 
1734
+ QueueHeartbeat(ed);
1705
1735
  Descriptors.push_back (ed);
1706
1736
  }
1707
1737
  NewDescriptors.clear();
@@ -1770,7 +1800,7 @@ const unsigned long EventMachine_t::_OpenFileForWriting (const char *filename)
1770
1800
  */
1771
1801
 
1772
1802
  if (!filename || !*filename)
1773
- return NULL;
1803
+ return 0;
1774
1804
 
1775
1805
  int fd = open (filename, O_CREAT|O_TRUNC|O_WRONLY|O_NONBLOCK, 0644);
1776
1806
 
@@ -1802,7 +1832,7 @@ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename
1802
1832
 
1803
1833
  // The whole rest of this function is only compiled on Unix systems.
1804
1834
  #ifdef OS_UNIX
1805
- unsigned long output_binding = NULL;
1835
+ unsigned long output_binding = 0;
1806
1836
 
1807
1837
  struct sockaddr_un s_sun;
1808
1838
 
@@ -1863,7 +1893,7 @@ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename
1863
1893
  fail:
1864
1894
  if (sd_accept != INVALID_SOCKET)
1865
1895
  closesocket (sd_accept);
1866
- return NULL;
1896
+ return 0;
1867
1897
  #endif // OS_UNIX
1868
1898
  }
1869
1899
 
@@ -1924,18 +1954,18 @@ const unsigned long EventMachine_t::Socketpair (char * const*cmd_strings)
1924
1954
  #ifdef OS_UNIX
1925
1955
  // Make sure the incoming array of command strings is sane.
1926
1956
  if (!cmd_strings)
1927
- return NULL;
1957
+ return 0;
1928
1958
  int j;
1929
- for (j=0; j < 100 && cmd_strings[j]; j++)
1959
+ for (j=0; cmd_strings[j]; j++)
1930
1960
  ;
1931
- if ((j==0) || (j==100))
1961
+ if (j==0)
1932
1962
  return NULL;
1933
1963
 
1934
- unsigned long output_binding = NULL;
1964
+ unsigned long output_binding = 0;
1935
1965
 
1936
1966
  int sv[2];
1937
1967
  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, sv) < 0)
1938
- return NULL;
1968
+ return 0;
1939
1969
  // from here, all early returns must close the pair of sockets.
1940
1970
 
1941
1971
  // Set the parent side of the socketpair nonblocking.
@@ -1945,7 +1975,7 @@ const unsigned long EventMachine_t::Socketpair (char * const*cmd_strings)
1945
1975
  if (!SetSocketNonblocking (sv[0])) {
1946
1976
  close (sv[0]);
1947
1977
  close (sv[1]);
1948
- return NULL;
1978
+ return 0;
1949
1979
  }
1950
1980
 
1951
1981
  pid_t f = fork();