Permalink
Browse files

fix epoll thread blocking issue by calling rb_thread_select on the ep…

…oll fd
  • Loading branch information...
1 parent 0319eb8 commit d684cc3b77a6c401295a3086b5671fe4ec335a64 @jakedouglas jakedouglas committed Nov 23, 2009
Showing with 47 additions and 9 deletions.
  1. +46 −9 ext/em.cpp
  2. +1 −0 ext/em.h
View
@@ -514,12 +514,28 @@ bool EventMachine_t::_RunEpollOnce()
assert (epfd != -1);
int s;
+ timeval tv = _TimeTilNextEvent();
+
#ifdef BUILD_FOR_RUBY
+ int ret = 0;
+ fd_set fdreads;
+
+ FD_ZERO(&fdreads);
+ FD_SET(epfd, &fdreads);
+
+ while ((ret = rb_thread_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
+ if (ret == -1) continue;
+ if (ret == 0) return true;
+ }
+
TRAP_BEG;
- #endif
- s = epoll_wait (epfd, epoll_events, MaxEvents, 50);
- #ifdef BUILD_FOR_RUBY
+ s = epoll_wait (epfd, epoll_events, MaxEvents, 0);
TRAP_END;
+ #else
+ int duration = 0;
+ duration = duration + (tv.tv_sec * 1000);
+ duration = duration + (tv.tv_usec / 1000);
+ s = epoll_wait (epfd, epoll_events, MaxEvents, duration);
#endif
if (s > 0) {
@@ -548,12 +564,6 @@ bool EventMachine_t::_RunEpollOnce()
EmSelect (0, NULL, NULL, NULL, &tv);
}
- #ifdef BUILD_FOR_RUBY
- if (!rb_thread_alone()) {
- rb_thread_schedule();
- }
- #endif
-
return true;
#else
throw std::runtime_error ("epoll is not implemented on this platform");
@@ -628,6 +638,33 @@ bool EventMachine_t::_RunKqueueOnce()
}
+/*********************************
+EventMachine_t::_TimeTilNextEvent
+*********************************/
+
+timeval EventMachine_t::_TimeTilNextEvent()
+{
+ multimap<uint64_t,EventableDescriptor*>::iterator heartbeats = Heartbeats.begin();
+ multimap<uint64_t,Timer_t>::iterator timers = Timers.begin();
+
+ uint64_t next_event = heartbeats->first;
+
+ if (timers->first != 0 && timers->first < next_event)
+ next_event = timers->first;
+
+ timeval tv;
+
+ if (next_event == 0) {
+ tv = Quantum;
+ } else {
+ uint64_t duration = next_event - MyCurrentLoopTime;
+ tv.tv_sec = duration / 1000000;
+ tv.tv_usec = duration % 1000000;
+ }
+
+ return tv;
+}
+
/*******************************
EventMachine_t::_CleanupSockets
*******************************/
View
@@ -156,6 +156,7 @@ class EventMachine_t
void _ModifyEpollEvent (EventableDescriptor*);
void _DispatchHeartbeats();
+ timeval _TimeTilNextEvent();
public:
void _ReadLoopBreaker();

0 comments on commit d684cc3

Please sign in to comment.