rev 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +16 -0
- data/README +1 -0
- data/Rakefile +10 -0
- data/ext/http11_client/http11_parser.c +563 -502
- data/ext/http11_client/http11_parser.rl +1 -1
- data/ext/libev/Changes +39 -1
- data/ext/libev/ev.c +286 -105
- data/ext/libev/ev.h +102 -34
- data/ext/libev/ev_poll.c +17 -14
- data/ext/libev/ev_select.c +4 -4
- data/ext/libev/ev_vars.h +14 -1
- data/ext/libev/ev_wrap.h +14 -0
- data/ext/rev/extconf.rb +15 -11
- data/ext/rev/rev_loop.c +35 -34
- data/ext/rev/rev_ssl.c +90 -3
- data/lib/rev.rb +8 -2
- data/lib/rev/http_client.rb +6 -6
- data/lib/rev/io.rb +53 -29
- data/lib/rev/io_watcher.rb +2 -1
- data/lib/rev/{watcher.rb → meta.rb} +3 -3
- data/lib/rev/server.rb +2 -2
- data/lib/rev/socket.rb +27 -21
- data/lib/rev/ssl.rb +35 -49
- data/lib/rev/timer_watcher.rb +1 -0
- data/rev.gemspec +2 -2
- metadata +3 -3
data/ext/libev/ev.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev native API header
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
@@ -78,6 +78,15 @@ typedef double ev_tstamp;
|
|
78
78
|
# define EV_EMBED_ENABLE 1
|
79
79
|
#endif
|
80
80
|
|
81
|
+
#ifndef EV_ASYNC_ENABLE
|
82
|
+
# define EV_ASYNC_ENABLE 1
|
83
|
+
#endif
|
84
|
+
|
85
|
+
#ifndef EV_ATOMIC_T
|
86
|
+
# include <signal.h>
|
87
|
+
# define EV_ATOMIC_T sig_atomic_t volatile
|
88
|
+
#endif
|
89
|
+
|
81
90
|
/*****************************************************************************/
|
82
91
|
|
83
92
|
#if EV_STAT_ENABLE
|
@@ -91,6 +100,8 @@ struct ev_loop;
|
|
91
100
|
# define EV_P_ EV_P,
|
92
101
|
# define EV_A loop
|
93
102
|
# define EV_A_ EV_A,
|
103
|
+
# define EV_DEFAULT_UC ev_default_loop_uc ()
|
104
|
+
# define EV_DEFAULT_UC_ EV_DEFAULT_UC,
|
94
105
|
# define EV_DEFAULT ev_default_loop (0)
|
95
106
|
# define EV_DEFAULT_ EV_DEFAULT,
|
96
107
|
#else
|
@@ -100,27 +111,37 @@ struct ev_loop;
|
|
100
111
|
# define EV_A_
|
101
112
|
# define EV_DEFAULT
|
102
113
|
# define EV_DEFAULT_
|
103
|
-
|
114
|
+
# define EV_DEFAULT_UC
|
115
|
+
# define EV_DEFAULT_UC_
|
104
116
|
# undef EV_EMBED_ENABLE
|
105
117
|
#endif
|
106
118
|
|
119
|
+
#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3
|
120
|
+
# define EV_INLINE static inline
|
121
|
+
#else
|
122
|
+
# define EV_INLINE static
|
123
|
+
#endif
|
124
|
+
|
125
|
+
/*****************************************************************************/
|
126
|
+
|
107
127
|
/* eventmask, revents, events... */
|
108
|
-
#define EV_UNDEF -
|
109
|
-
#define EV_NONE
|
110
|
-
#define EV_READ
|
111
|
-
#define EV_WRITE
|
112
|
-
#define EV_IOFDSET
|
113
|
-
#define EV_TIMEOUT
|
114
|
-
#define EV_PERIODIC
|
115
|
-
#define EV_SIGNAL
|
116
|
-
#define EV_CHILD
|
117
|
-
#define EV_STAT
|
118
|
-
#define EV_IDLE
|
119
|
-
#define EV_PREPARE
|
120
|
-
#define EV_CHECK
|
121
|
-
#define EV_EMBED
|
122
|
-
#define EV_FORK
|
123
|
-
#define
|
128
|
+
#define EV_UNDEF -1 /* guaranteed to be invalid */
|
129
|
+
#define EV_NONE 0x00 /* no events */
|
130
|
+
#define EV_READ 0x01 /* ev_io detected read will not block */
|
131
|
+
#define EV_WRITE 0x02 /* ev_io detected write will not block */
|
132
|
+
#define EV_IOFDSET 0x80 /* internal use only */
|
133
|
+
#define EV_TIMEOUT 0x00000100 /* timer timed out */
|
134
|
+
#define EV_PERIODIC 0x00000200 /* periodic timer timed out */
|
135
|
+
#define EV_SIGNAL 0x00000400 /* signal was received */
|
136
|
+
#define EV_CHILD 0x00000800 /* child/pid had status change */
|
137
|
+
#define EV_STAT 0x00001000 /* stat data changed */
|
138
|
+
#define EV_IDLE 0x00002000 /* event loop is idling */
|
139
|
+
#define EV_PREPARE 0x00004000 /* event loop about to poll */
|
140
|
+
#define EV_CHECK 0x00008000 /* event loop finished poll */
|
141
|
+
#define EV_EMBED 0x00010000 /* embedded event loop needs sweep */
|
142
|
+
#define EV_FORK 0x00020000 /* event loop resumed in child */
|
143
|
+
#define EV_ASYNC 0x00040000 /* async intra-loop signal */
|
144
|
+
#define EV_ERROR 0x80000000 /* sent when an error occurs */
|
124
145
|
|
125
146
|
/* can be used to add custom fields to all watchers, while losing binary compatibility */
|
126
147
|
#ifndef EV_COMMON
|
@@ -307,6 +328,19 @@ typedef struct ev_embed
|
|
307
328
|
} ev_embed;
|
308
329
|
#endif
|
309
330
|
|
331
|
+
#if EV_ASYNC_ENABLE
|
332
|
+
/* invoked when somebody calls ev_async_send on the watcher */
|
333
|
+
/* revent EV_ASYNC */
|
334
|
+
typedef struct ev_async
|
335
|
+
{
|
336
|
+
EV_WATCHER (ev_async)
|
337
|
+
|
338
|
+
EV_ATOMIC_T sent; /* private */
|
339
|
+
} ev_async;
|
340
|
+
|
341
|
+
# define ev_async_pending(w) ((w)->sent + 0)
|
342
|
+
#endif
|
343
|
+
|
310
344
|
/* the presence of this union forces similar struct layout */
|
311
345
|
union ev_any_watcher
|
312
346
|
{
|
@@ -332,21 +366,24 @@ union ev_any_watcher
|
|
332
366
|
#if EV_EMBED_ENABLE
|
333
367
|
struct ev_embed embed;
|
334
368
|
#endif
|
369
|
+
#if EV_ASYNC_ENABLE
|
370
|
+
struct ev_async async;
|
371
|
+
#endif
|
335
372
|
};
|
336
373
|
|
337
374
|
/* bits for ev_default_loop and ev_loop_new */
|
338
375
|
/* the default */
|
339
|
-
#define EVFLAG_AUTO
|
376
|
+
#define EVFLAG_AUTO 0x00000000U /* not quite a mask */
|
340
377
|
/* flag bits */
|
341
|
-
#define EVFLAG_NOENV
|
342
|
-
#define EVFLAG_FORKCHECK
|
378
|
+
#define EVFLAG_NOENV 0x01000000U /* do NOT consult environment */
|
379
|
+
#define EVFLAG_FORKCHECK 0x02000000U /* check for a fork in each iteration */
|
343
380
|
/* method bits to be ored together */
|
344
|
-
#define EVBACKEND_SELECT
|
345
|
-
#define EVBACKEND_POLL
|
346
|
-
#define EVBACKEND_EPOLL
|
347
|
-
#define EVBACKEND_KQUEUE
|
348
|
-
#define EVBACKEND_DEVPOLL
|
349
|
-
#define EVBACKEND_PORT
|
381
|
+
#define EVBACKEND_SELECT 0x00000001U /* about anywhere */
|
382
|
+
#define EVBACKEND_POLL 0x00000002U /* !win */
|
383
|
+
#define EVBACKEND_EPOLL 0x00000004U /* linux */
|
384
|
+
#define EVBACKEND_KQUEUE 0x00000008U /* bsd */
|
385
|
+
#define EVBACKEND_DEVPOLL 0x00000010U /* solaris 8 */ /* NYI */
|
386
|
+
#define EVBACKEND_PORT 0x00000020U /* solaris 10 */
|
350
387
|
|
351
388
|
#if EV_PROTOTYPES
|
352
389
|
int ev_version_major (void);
|
@@ -374,18 +411,29 @@ void ev_set_allocator (void *(*cb)(void *ptr, long size));
|
|
374
411
|
void ev_set_syserr_cb (void (*cb)(const char *msg));
|
375
412
|
|
376
413
|
# if EV_MULTIPLICITY
|
414
|
+
EV_INLINE struct ev_loop *
|
415
|
+
ev_default_loop_uc (void)
|
416
|
+
{
|
417
|
+
extern struct ev_loop *ev_default_loop_ptr;
|
418
|
+
|
419
|
+
return ev_default_loop_ptr;
|
420
|
+
}
|
421
|
+
|
377
422
|
/* the default loop is the only one that handles signals and child watchers */
|
378
423
|
/* you can call this as often as you like */
|
379
|
-
|
424
|
+
EV_INLINE struct ev_loop *
|
380
425
|
ev_default_loop (unsigned int flags)
|
381
426
|
{
|
382
|
-
|
383
|
-
extern struct ev_loop *ev_default_loop_init (unsigned int flags);
|
427
|
+
struct ev_loop *loop = ev_default_loop_uc ();
|
384
428
|
|
385
|
-
if (!
|
386
|
-
|
429
|
+
if (!loop)
|
430
|
+
{
|
431
|
+
extern struct ev_loop *ev_default_loop_init (unsigned int flags);
|
387
432
|
|
388
|
-
|
433
|
+
loop = ev_default_loop_init (flags);
|
434
|
+
}
|
435
|
+
|
436
|
+
return loop;
|
389
437
|
}
|
390
438
|
|
391
439
|
/* create and destroy alternative loops that don't handle signals */
|
@@ -399,7 +447,7 @@ ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after
|
|
399
447
|
|
400
448
|
int ev_default_loop (unsigned int flags); /* returns true when successful */
|
401
449
|
|
402
|
-
|
450
|
+
EV_INLINE ev_tstamp
|
403
451
|
ev_now (void)
|
404
452
|
{
|
405
453
|
extern ev_tstamp ev_rt_now;
|
@@ -408,6 +456,18 @@ ev_now (void)
|
|
408
456
|
}
|
409
457
|
# endif
|
410
458
|
|
459
|
+
EV_INLINE int
|
460
|
+
ev_is_default_loop (EV_P)
|
461
|
+
{
|
462
|
+
#if EV_MULTIPLICITY
|
463
|
+
extern struct ev_loop *ev_default_loop_ptr;
|
464
|
+
|
465
|
+
return !!(EV_A == ev_default_loop_ptr);
|
466
|
+
#else
|
467
|
+
return 1;
|
468
|
+
#endif
|
469
|
+
}
|
470
|
+
|
411
471
|
void ev_default_destroy (void); /* destroy the default loop */
|
412
472
|
/* this needs to be called after fork, to duplicate the default loop */
|
413
473
|
/* if you create alternative loops you have to call ev_loop_fork on them */
|
@@ -465,6 +525,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
|
|
465
525
|
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */
|
466
526
|
#define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0)
|
467
527
|
#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */
|
528
|
+
#define ev_async_set(ev) do { (ev)->sent = 0; } while (0)
|
468
529
|
|
469
530
|
#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
|
470
531
|
#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
|
@@ -477,6 +538,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
|
|
477
538
|
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
|
478
539
|
#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)
|
479
540
|
#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
|
541
|
+
#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)
|
480
542
|
|
481
543
|
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
|
482
544
|
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
|
@@ -552,6 +614,12 @@ void ev_embed_stop (EV_P_ ev_embed *w);
|
|
552
614
|
void ev_embed_sweep (EV_P_ ev_embed *w);
|
553
615
|
# endif
|
554
616
|
|
617
|
+
# if EV_ASYNC_ENABLE
|
618
|
+
void ev_async_start (EV_P_ ev_async *w);
|
619
|
+
void ev_async_stop (EV_P_ ev_async *w);
|
620
|
+
void ev_async_send (EV_P_ ev_async *w);
|
621
|
+
# endif
|
622
|
+
|
555
623
|
#endif
|
556
624
|
|
557
625
|
#ifdef __cplusplus
|
data/ext/libev/ev_poll.c
CHANGED
@@ -86,7 +86,7 @@ poll_modify (EV_P_ int fd, int oev, int nev)
|
|
86
86
|
static void
|
87
87
|
poll_poll (EV_P_ ev_tstamp timeout)
|
88
88
|
{
|
89
|
-
|
89
|
+
struct pollfd *p;
|
90
90
|
int res = poll (polls, pollcnt, (int)ceil (timeout * 1000.));
|
91
91
|
|
92
92
|
if (expect_false (res < 0))
|
@@ -97,20 +97,23 @@ poll_poll (EV_P_ ev_tstamp timeout)
|
|
97
97
|
fd_enomem (EV_A);
|
98
98
|
else if (errno != EINTR)
|
99
99
|
syserr ("(libev) poll");
|
100
|
-
|
101
|
-
return;
|
102
100
|
}
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
101
|
+
else
|
102
|
+
for (p = polls; res; ++p)
|
103
|
+
if (expect_false (p->revents)) /* this expect is debatable */
|
104
|
+
{
|
105
|
+
--res;
|
106
|
+
|
107
|
+
if (expect_false (p->revents & POLLNVAL))
|
108
|
+
fd_kill (EV_A_ p->fd);
|
109
|
+
else
|
110
|
+
fd_event (
|
111
|
+
EV_A_
|
112
|
+
p->fd,
|
113
|
+
(p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
|
114
|
+
| (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
|
115
|
+
);
|
116
|
+
}
|
114
117
|
}
|
115
118
|
|
116
119
|
int inline_size
|
data/ext/libev/ev_select.c
CHANGED
@@ -95,8 +95,8 @@ select_modify (EV_P_ int fd, int oev, int nev)
|
|
95
95
|
|
96
96
|
#else
|
97
97
|
|
98
|
-
int
|
99
|
-
|
98
|
+
int word = fd / NFDBITS;
|
99
|
+
fd_mask mask = 1UL << (fd % NFDBITS);
|
100
100
|
|
101
101
|
if (expect_false (vec_max < word + 1))
|
102
102
|
{
|
@@ -108,8 +108,8 @@ select_modify (EV_P_ int fd, int oev, int nev)
|
|
108
108
|
vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */
|
109
109
|
|
110
110
|
for (; vec_max < new_max; ++vec_max)
|
111
|
-
((fd_mask *)vec_ri)[vec_max] =
|
112
|
-
((fd_mask *)vec_wi)[vec_max] = 0;
|
111
|
+
((fd_mask *)vec_ri) [vec_max] =
|
112
|
+
((fd_mask *)vec_wi) [vec_max] = 0;
|
113
113
|
}
|
114
114
|
|
115
115
|
((fd_mask *)vec_ri) [word] |= mask;
|
data/ext/libev/ev_vars.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* loop member variable declarations
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
@@ -55,6 +55,12 @@ VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */
|
|
55
55
|
VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))
|
56
56
|
VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout))
|
57
57
|
|
58
|
+
#if EV_USE_EVENTFD || EV_GENWRAP
|
59
|
+
VARx(int, evfd)
|
60
|
+
#endif
|
61
|
+
VAR (evpipe, int evpipe [2])
|
62
|
+
VARx(ev_io, pipeev)
|
63
|
+
|
58
64
|
#if !defined(_WIN32) || EV_GENWRAP
|
59
65
|
VARx(pid_t, curpid)
|
60
66
|
#endif
|
@@ -137,6 +143,13 @@ VARx(int, forkmax)
|
|
137
143
|
VARx(int, forkcnt)
|
138
144
|
#endif
|
139
145
|
|
146
|
+
VARx(EV_ATOMIC_T, gotasync)
|
147
|
+
#if EV_ASYNC_ENABLE || EV_GENWRAP
|
148
|
+
VARx(struct ev_async **, asyncs)
|
149
|
+
VARx(int, asyncmax)
|
150
|
+
VARx(int, asynccnt)
|
151
|
+
#endif
|
152
|
+
|
140
153
|
#if EV_USE_INOTIFY || EV_GENWRAP
|
141
154
|
VARx(int, fs_fd)
|
142
155
|
VARx(ev_io, fs_w)
|
data/ext/libev/ev_wrap.h
CHANGED
@@ -13,6 +13,9 @@
|
|
13
13
|
#define backend_fudge ((loop)->backend_fudge)
|
14
14
|
#define backend_modify ((loop)->backend_modify)
|
15
15
|
#define backend_poll ((loop)->backend_poll)
|
16
|
+
#define evfd ((loop)->evfd)
|
17
|
+
#define evpipe ((loop)->evpipe)
|
18
|
+
#define pipeev ((loop)->pipeev)
|
16
19
|
#define curpid ((loop)->curpid)
|
17
20
|
#define postfork ((loop)->postfork)
|
18
21
|
#define vec_ri ((loop)->vec_ri)
|
@@ -61,6 +64,10 @@
|
|
61
64
|
#define forks ((loop)->forks)
|
62
65
|
#define forkmax ((loop)->forkmax)
|
63
66
|
#define forkcnt ((loop)->forkcnt)
|
67
|
+
#define gotasync ((loop)->gotasync)
|
68
|
+
#define asyncs ((loop)->asyncs)
|
69
|
+
#define asyncmax ((loop)->asyncmax)
|
70
|
+
#define asynccnt ((loop)->asynccnt)
|
64
71
|
#define fs_fd ((loop)->fs_fd)
|
65
72
|
#define fs_w ((loop)->fs_w)
|
66
73
|
#define fs_hash ((loop)->fs_hash)
|
@@ -78,6 +85,9 @@
|
|
78
85
|
#undef backend_fudge
|
79
86
|
#undef backend_modify
|
80
87
|
#undef backend_poll
|
88
|
+
#undef evfd
|
89
|
+
#undef evpipe
|
90
|
+
#undef pipeev
|
81
91
|
#undef curpid
|
82
92
|
#undef postfork
|
83
93
|
#undef vec_ri
|
@@ -126,6 +136,10 @@
|
|
126
136
|
#undef forks
|
127
137
|
#undef forkmax
|
128
138
|
#undef forkcnt
|
139
|
+
#undef gotasync
|
140
|
+
#undef asyncs
|
141
|
+
#undef asyncmax
|
142
|
+
#undef asynccnt
|
129
143
|
#undef fs_fd
|
130
144
|
#undef fs_w
|
131
145
|
#undef fs_hash
|
data/ext/rev/extconf.rb
CHANGED
@@ -1,48 +1,52 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
cflags = []
|
4
3
|
libs = []
|
5
4
|
|
5
|
+
$defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
|
6
|
+
|
6
7
|
if have_func('rb_thread_blocking_region')
|
7
|
-
|
8
|
+
$defs << '-DHAVE_RB_THREAD_BLOCKING_REGION'
|
9
|
+
end
|
10
|
+
|
11
|
+
if have_func('rb_str_set_len')
|
12
|
+
$defs << '-DHAVE_RB_STR_SET_LEN'
|
8
13
|
end
|
9
14
|
|
10
15
|
if have_header('sys/select.h')
|
11
|
-
|
16
|
+
$defs << '-DEV_USE_SELECT'
|
12
17
|
end
|
13
18
|
|
14
19
|
if have_header('poll.h')
|
15
|
-
|
20
|
+
$defs << '-DEV_USE_POLL'
|
16
21
|
end
|
17
22
|
|
18
23
|
if have_header('sys/epoll.h')
|
19
|
-
|
24
|
+
$defs << '-DEV_USE_EPOLL'
|
20
25
|
end
|
21
26
|
|
22
27
|
if have_header('sys/event.h') and have_header('sys/queue.h')
|
23
|
-
|
28
|
+
$defs << '-DEV_USE_KQUEUE'
|
24
29
|
end
|
25
30
|
|
26
31
|
if have_header('port.h')
|
27
|
-
|
32
|
+
$defs << '-DEV_USE_PORT'
|
28
33
|
end
|
29
34
|
|
30
35
|
if have_header('openssl/ssl.h')
|
31
|
-
|
36
|
+
$defs << '-DHAVE_OPENSSL_SSL_H'
|
32
37
|
libs << '-lssl -lcrypto'
|
33
38
|
end
|
34
39
|
|
35
40
|
# ncpu detection specifics
|
36
41
|
case RUBY_PLATFORM
|
37
42
|
when /linux/
|
38
|
-
|
43
|
+
$defs << '-DHAVE_LINUX_PROCFS'
|
39
44
|
else
|
40
45
|
if have_func('sysctlbyname', ['sys/param.h', 'sys/sysctl.h'])
|
41
|
-
|
46
|
+
$defs << '-DHAVE_SYSCTLBYNAME'
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
45
|
-
$CFLAGS << ' ' << cflags.join(' ')
|
46
50
|
$LIBS << ' ' << libs.join(' ')
|
47
51
|
|
48
52
|
dir_config('rev_ext')
|
data/ext/rev/rev_loop.c
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
|
7
7
|
#include <assert.h>
|
8
8
|
#include "ruby.h"
|
9
|
+
#include "rubysig.h"
|
9
10
|
|
10
11
|
#define EV_STANDALONE 1
|
11
12
|
#include "../libev/ev.h"
|
@@ -28,6 +29,10 @@ static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data);
|
|
28
29
|
static void Rev_Loop_dispatch_events(struct Rev_Loop *loop_data);
|
29
30
|
|
30
31
|
#define DEFAULT_EVENTBUF_SIZE 32
|
32
|
+
#define RUN_LOOP(loop_data, options) \
|
33
|
+
loop_data->running = 1; \
|
34
|
+
ev_loop(loop_data->ev_loop, options); \
|
35
|
+
loop_data->running = 0;
|
31
36
|
|
32
37
|
/*
|
33
38
|
* Rev::Loop represents an event loop. Event watchers can be attached and
|
@@ -52,7 +57,6 @@ static VALUE Rev_Loop_allocate(VALUE klass)
|
|
52
57
|
struct Rev_Loop *loop = (struct Rev_Loop *)xmalloc(sizeof(struct Rev_Loop));
|
53
58
|
|
54
59
|
loop->ev_loop = 0;
|
55
|
-
|
56
60
|
loop->running = 0;
|
57
61
|
loop->events_received = 0;
|
58
62
|
loop->eventbuf_size = DEFAULT_EVENTBUF_SIZE;
|
@@ -173,22 +177,19 @@ void Rev_Loop_process_event(VALUE watcher, int revents)
|
|
173
177
|
static VALUE Rev_Loop_run_once(VALUE self)
|
174
178
|
{
|
175
179
|
struct Rev_Loop *loop_data;
|
180
|
+
VALUE nevents;
|
181
|
+
|
176
182
|
Data_Get_Struct(self, struct Rev_Loop, loop_data);
|
177
183
|
|
178
|
-
if(loop_data->running)
|
179
|
-
rb_raise(rb_eRuntimeError, "cannot run loop from within a callback");
|
180
|
-
|
181
184
|
assert(loop_data->ev_loop && !loop_data->events_received);
|
182
|
-
|
183
|
-
loop_data
|
184
|
-
|
185
|
-
Rev_Loop_ev_loop_oneshot(loop_data);
|
185
|
+
|
186
|
+
Rev_Loop_ev_loop_oneshot(loop_data);
|
186
187
|
Rev_Loop_dispatch_events(loop_data);
|
188
|
+
|
189
|
+
nevents = INT2NUM(loop_data->events_received);
|
187
190
|
loop_data->events_received = 0;
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
return Qnil;
|
191
|
+
|
192
|
+
return nevents;
|
192
193
|
}
|
193
194
|
|
194
195
|
/* Ruby 1.9 supports blocking system calls through rb_thread_blocking_region() */
|
@@ -197,16 +198,17 @@ static VALUE Rev_Loop_run_once(VALUE self)
|
|
197
198
|
static VALUE Rev_Loop_ev_loop_oneshot_blocking(void *ptr)
|
198
199
|
{
|
199
200
|
/* The libev loop has now escaped through the Global VM Lock unscathed! */
|
200
|
-
struct
|
201
|
+
struct Rev_Loop *loop_data = (struct Rev_Loop *)ptr;
|
201
202
|
|
202
|
-
|
203
|
+
RUN_LOOP(loop_data, EVLOOP_ONESHOT);
|
204
|
+
|
203
205
|
return Qnil;
|
204
206
|
}
|
205
207
|
|
206
208
|
static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data)
|
207
209
|
{
|
208
210
|
/* Use Ruby 1.9's rb_thread_blocking_region call to make a blocking system call */
|
209
|
-
rb_thread_blocking_region(Rev_Loop_ev_loop_oneshot_blocking, loop_data
|
211
|
+
rb_thread_blocking_region(Rev_Loop_ev_loop_oneshot_blocking, loop_data, RB_UBF_DFL, 0);
|
210
212
|
}
|
211
213
|
#endif
|
212
214
|
|
@@ -215,11 +217,12 @@ static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data)
|
|
215
217
|
#ifndef HAVE_EV_LOOP_ONESHOT
|
216
218
|
#define BLOCKING_INTERVAL 0.01 /* Block for 10ms at a time */
|
217
219
|
|
218
|
-
/* Stub callback */
|
220
|
+
/* Stub for scheduler's ev_timer callback */
|
219
221
|
static void timer_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents)
|
220
222
|
{
|
221
223
|
}
|
222
224
|
|
225
|
+
/* Run the event loop, calling rb_thread_schedule every 10ms */
|
223
226
|
static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data)
|
224
227
|
{
|
225
228
|
struct ev_timer timer;
|
@@ -229,15 +232,14 @@ static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data)
|
|
229
232
|
ev_timer_init(&timer, timer_callback, BLOCKING_INTERVAL, BLOCKING_INTERVAL);
|
230
233
|
ev_timer_start(loop_data->ev_loop, &timer);
|
231
234
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
+
/* Loop until we receive events */
|
236
|
+
while(!loop_data->events_received) {
|
237
|
+
TRAP_BEG;
|
238
|
+
RUN_LOOP(loop_data, EVLOOP_ONESHOT);
|
239
|
+
TRAP_END;
|
235
240
|
|
236
|
-
|
237
|
-
|
238
|
-
tv.tv_usec = 0;
|
239
|
-
rb_thread_select(0, NULL, NULL, NULL, &tv);
|
240
|
-
} while(!loop_data->events_received);
|
241
|
+
rb_thread_schedule();
|
242
|
+
}
|
241
243
|
|
242
244
|
ev_timer_stop(loop_data->ev_loop, &timer);
|
243
245
|
}
|
@@ -245,27 +247,26 @@ static void Rev_Loop_ev_loop_oneshot(struct Rev_Loop *loop_data)
|
|
245
247
|
|
246
248
|
/**
|
247
249
|
* call-seq:
|
248
|
-
* Rev::Loop.
|
250
|
+
* Rev::Loop.run_nonblock -> nil
|
249
251
|
*
|
250
252
|
* Run the Rev::Loop once, but return immediately if there are no pending events.
|
251
253
|
*/
|
252
254
|
static VALUE Rev_Loop_run_nonblock(VALUE self)
|
253
255
|
{
|
254
256
|
struct Rev_Loop *loop_data;
|
257
|
+
VALUE nevents;
|
258
|
+
|
255
259
|
Data_Get_Struct(self, struct Rev_Loop, loop_data);
|
256
260
|
|
257
|
-
if(loop_data->running)
|
258
|
-
rb_raise(rb_eRuntimeError, "cannot run loop from within a callback");
|
259
|
-
|
260
261
|
assert(loop_data->ev_loop && !loop_data->events_received);
|
261
262
|
|
262
|
-
loop_data
|
263
|
-
ev_loop(loop_data->ev_loop, EVLOOP_NONBLOCK);
|
263
|
+
RUN_LOOP(loop_data, EVLOOP_NONBLOCK);
|
264
264
|
Rev_Loop_dispatch_events(loop_data);
|
265
|
+
|
266
|
+
nevents = INT2NUM(loop_data->events_received);
|
265
267
|
loop_data->events_received = 0;
|
266
|
-
|
267
|
-
|
268
|
-
return Qnil;
|
268
|
+
|
269
|
+
return nevents;
|
269
270
|
}
|
270
271
|
|
271
272
|
static void Rev_Loop_dispatch_events(struct Rev_Loop *loop_data)
|
@@ -283,4 +284,4 @@ static void Rev_Loop_dispatch_events(struct Rev_Loop *loop_data)
|
|
283
284
|
Data_Get_Struct(loop_data->eventbuf[i].watcher, struct Rev_Watcher, watcher_data);
|
284
285
|
watcher_data->dispatch_callback(loop_data->eventbuf[i].watcher, loop_data->eventbuf[i].revents);
|
285
286
|
}
|
286
|
-
}
|
287
|
+
}
|