ry / ebb fork watch download tarball
public this repo is viewable by everyone
Description: web server
Homepage: http://ebb.rubyforge.org
Clone URL: git://github.com/ry/ebb.git
try rb_thread_select() again
Ryan Dahl (author)
2 months ago
commit  0b0e45780854a7db3a8f0c1700976ddda41b3e40
tree    77be86c0ec36f483414ed5e82820c04d7c6ff580
parent  0a07adc53a3efabc3e20239a29163d86dd3c47b7
...
28
29
30
 
31
32
33
...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
 
 
81
 
82
83
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
86
87
...
270
271
272
 
 
 
 
 
273
274
275
...
28
29
30
31
32
33
34
...
55
56
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
59
60
61
62
 
 
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
...
267
268
269
270
271
272
273
274
275
276
277
0
@@ -28,6 +28,7 @@ static VALUE global_http_host;
0
  */
0
 static ebb_server *server;
0
 struct ev_loop *loop;
0
+struct ev_idle idle_watcher;
0
 
0
 /* Variables with a leading underscore are C-level variables */
0
 
0
@@ -54,34 +55,30 @@ VALUE server_listen_on_port(VALUE _, VALUE port)
0
 static void
0
 oneshot_timeout (struct ev_loop *loop, struct ev_timer *w, int revents) {;}
0
 
0
-VALUE server_process_connections(VALUE _)
0
-{
0
- /* This function is super hacky. The libev loop is called for one iteration
0
- * this means that any pending events are handled. If no events exist then
0
- * the function blocks. We want blocking so that the while loop in ruby
0
- * doesn't race away - however there is a need to continue to process other
0
- * ruby threads which are running. While this function is being called
0
- * other ruby threads cannot execute.
0
- * So we set this timeout event which breaks the block after 0.1 seconds.
0
- * Additionally we make sure that other threads get enough processing time
0
- * by calling rb_thread_schedule() many times.
0
- *
0
- * Instead we should probably use rb_thread_select on server->fd when no
0
- * clients are in_use? Whatever happens here, one should make sure the
0
- * 'wait' benchmark is running as quickly with Ebb as it does with mongrel.
0
- */
0
- ev_timer timeout;
0
- ev_timer_init (&timeout, oneshot_timeout, 0.1, 0.);
0
- ev_timer_start (loop, &timeout);
0
- ev_loop(loop, EVLOOP_ONESHOT);
0
- ev_timer_stop(loop, &timeout);
0
-
0
- /* Call rb_thread_schedule() proportional to the number of rb threads running */
0
- /* SO HACKY! Anyone have a better way to do this? */
0
+static void
0
+idle_cb (struct ev_loop *loop, struct ev_idle *w, int revents) {
0
   int i;
0
+ int running_clients = FALSE;
0
   for(i = 0; i < EBB_MAX_CLIENTS; i++)
0
- if(server->clients[i].in_use)
0
- rb_thread_schedule();
0
+ if(server->clients[i].open) {
0
+ running_clients = TRUE;
0
+ break;
0
+ }
0
+ if(!running_clients) {
0
+ fd_set fds;
0
+ struct timeval tv = { tv_sec: 1, tv_usec: 0 };
0
+ FD_ZERO(&fds);
0
+ FD_SET(server->fd, &fds);
0
+ /* sit in ruby thread select for a second when there are no connections */
0
+ // printf("enter select()\n");
0
+ rb_thread_select(server->fd+1, &fds, &fds, &fds, &tv);
0
+ // printf("leave select()\n");
0
+ }
0
+}
0
+
0
+VALUE server_process_connections(VALUE _)
0
+{
0
+ ev_loop(loop, EVLOOP_NONBLOCK);
0
   
0
   return Qnil;
0
 }
0
@@ -270,6 +267,11 @@ void Init_ebb_ext()
0
   
0
   /* initialize ebb_server */
0
   loop = ev_default_loop (0);
0
+ ev_idle_init (&idle_watcher, idle_cb);
0
+ ev_idle_start (loop, &idle_watcher);
0
+
0
+
0
+
0
   server = ebb_server_alloc();
0
   VALUE waiting_clients = rb_ary_new();
0
   rb_iv_set(mFFI, "@waiting_clients", waiting_clients);

Comments

    No one has commented yet.