nio4r 0.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +20 -0
- data/.rspec +4 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +20 -0
- data/README.md +123 -0
- data/Rakefile +9 -0
- data/ext/libev/Changes +388 -0
- data/ext/libev/LICENSE +36 -0
- data/ext/libev/README +58 -0
- data/ext/libev/README.embed +3 -0
- data/ext/libev/ev.c +3913 -0
- data/ext/libev/ev.h +829 -0
- data/ext/libev/ev_epoll.c +266 -0
- data/ext/libev/ev_kqueue.c +198 -0
- data/ext/libev/ev_poll.c +148 -0
- data/ext/libev/ev_port.c +179 -0
- data/ext/libev/ev_select.c +310 -0
- data/ext/libev/ev_vars.h +203 -0
- data/ext/libev/ev_win32.c +153 -0
- data/ext/libev/ev_wrap.h +196 -0
- data/ext/libev/test_libev_win32.c +123 -0
- data/ext/nio4r/extconf.rb +44 -0
- data/ext/nio4r/libev.h +8 -0
- data/ext/nio4r/monitor.c +164 -0
- data/ext/nio4r/nio4r.h +53 -0
- data/ext/nio4r/nio4r_ext.c +16 -0
- data/ext/nio4r/selector.c +370 -0
- data/lib/nio/jruby/monitor.rb +26 -0
- data/lib/nio/jruby/selector.rb +110 -0
- data/lib/nio/monitor.rb +21 -0
- data/lib/nio/selector.rb +101 -0
- data/lib/nio/version.rb +3 -0
- data/lib/nio.rb +30 -0
- data/nio4r.gemspec +23 -0
- data/spec/nio/monitor_spec.rb +36 -0
- data/spec/nio/selector_spec.rb +197 -0
- data/spec/spec_helper.rb +3 -0
- data/tasks/extension.rake +10 -0
- data/tasks/rspec.rake +7 -0
- metadata +121 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
/*
|
2
|
+
* libev win32 compatibility cruft (_not_ a backend)
|
3
|
+
*
|
4
|
+
* Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without modifica-
|
8
|
+
* tion, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
11
|
+
* this list of conditions and the following disclaimer.
|
12
|
+
*
|
13
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
* notice, this list of conditions and the following disclaimer in the
|
15
|
+
* documentation and/or other materials provided with the distribution.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
18
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
19
|
+
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
20
|
+
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
21
|
+
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
22
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
23
|
+
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
24
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
25
|
+
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
26
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*
|
28
|
+
* Alternatively, the contents of this file may be used under the terms of
|
29
|
+
* the GNU General Public License ("GPL") version 2 or any later version,
|
30
|
+
* in which case the provisions of the GPL are applicable instead of
|
31
|
+
* the above. If you wish to allow the use of your version of this file
|
32
|
+
* only under the terms of the GPL and not to allow others to use your
|
33
|
+
* version of this file under the BSD license, indicate your decision
|
34
|
+
* by deleting the provisions above and replace them with the notice
|
35
|
+
* and other provisions required by the GPL. If you do not delete the
|
36
|
+
* provisions above, a recipient may use your version of this file under
|
37
|
+
* either the BSD or the GPL.
|
38
|
+
*/
|
39
|
+
|
40
|
+
#ifdef _WIN32
|
41
|
+
|
42
|
+
/* timeb.h is actually xsi legacy functionality */
|
43
|
+
#include <sys/timeb.h>
|
44
|
+
|
45
|
+
/* note: the comment below could not be substantiated, but what would I care */
|
46
|
+
/* MSDN says this is required to handle SIGFPE */
|
47
|
+
/* my wild guess would be that using something floating-pointy is required */
|
48
|
+
/* for the crt to do something about it */
|
49
|
+
volatile double SIGFPE_REQ = 0.0f;
|
50
|
+
|
51
|
+
/* oh, the humanity! */
|
52
|
+
static int
|
53
|
+
ev_pipe (int filedes [2])
|
54
|
+
{
|
55
|
+
struct sockaddr_in addr = { 0 };
|
56
|
+
int addr_size = sizeof (addr);
|
57
|
+
struct sockaddr_in adr2;
|
58
|
+
int adr2_size = sizeof (adr2);
|
59
|
+
SOCKET listener;
|
60
|
+
SOCKET sock [2] = { -1, -1 };
|
61
|
+
|
62
|
+
if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
|
63
|
+
return -1;
|
64
|
+
|
65
|
+
addr.sin_family = AF_INET;
|
66
|
+
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
67
|
+
addr.sin_port = 0;
|
68
|
+
|
69
|
+
if (bind (listener, (struct sockaddr *)&addr, addr_size))
|
70
|
+
goto fail;
|
71
|
+
|
72
|
+
if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
|
73
|
+
goto fail;
|
74
|
+
|
75
|
+
if (listen (listener, 1))
|
76
|
+
goto fail;
|
77
|
+
|
78
|
+
if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
|
79
|
+
goto fail;
|
80
|
+
|
81
|
+
if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
|
82
|
+
goto fail;
|
83
|
+
|
84
|
+
if ((sock [1] = accept (listener, 0, 0)) < 0)
|
85
|
+
goto fail;
|
86
|
+
|
87
|
+
/* windows vista returns fantasy port numbers for sockets:
|
88
|
+
* example for two interconnected tcp sockets:
|
89
|
+
*
|
90
|
+
* (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
|
91
|
+
* (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
|
92
|
+
* (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
|
93
|
+
* (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
|
94
|
+
*
|
95
|
+
* wow! tridirectional sockets!
|
96
|
+
*
|
97
|
+
* this way of checking ports seems to work:
|
98
|
+
*/
|
99
|
+
if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
|
100
|
+
goto fail;
|
101
|
+
|
102
|
+
if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
|
103
|
+
goto fail;
|
104
|
+
|
105
|
+
errno = WSAEINVAL;
|
106
|
+
if (addr_size != adr2_size
|
107
|
+
|| addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
|
108
|
+
|| addr.sin_port != adr2.sin_port)
|
109
|
+
goto fail;
|
110
|
+
|
111
|
+
closesocket (listener);
|
112
|
+
|
113
|
+
#if EV_SELECT_IS_WINSOCKET
|
114
|
+
filedes [0] = EV_WIN32_HANDLE_TO_FD (sock [0]);
|
115
|
+
filedes [1] = EV_WIN32_HANDLE_TO_FD (sock [1]);
|
116
|
+
#else
|
117
|
+
/* when select isn't winsocket, we also expect socket, connect, accept etc.
|
118
|
+
* to work on fds */
|
119
|
+
filedes [0] = sock [0];
|
120
|
+
filedes [1] = sock [1];
|
121
|
+
#endif
|
122
|
+
|
123
|
+
return 0;
|
124
|
+
|
125
|
+
fail:
|
126
|
+
closesocket (listener);
|
127
|
+
|
128
|
+
if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
|
129
|
+
if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
|
130
|
+
|
131
|
+
return -1;
|
132
|
+
}
|
133
|
+
|
134
|
+
#undef pipe
|
135
|
+
#define pipe(filedes) ev_pipe (filedes)
|
136
|
+
|
137
|
+
#define EV_HAVE_EV_TIME 1
|
138
|
+
ev_tstamp
|
139
|
+
ev_time (void)
|
140
|
+
{
|
141
|
+
FILETIME ft;
|
142
|
+
ULARGE_INTEGER ui;
|
143
|
+
|
144
|
+
GetSystemTimeAsFileTime (&ft);
|
145
|
+
ui.u.LowPart = ft.dwLowDateTime;
|
146
|
+
ui.u.HighPart = ft.dwHighDateTime;
|
147
|
+
|
148
|
+
/* msvc cannot convert ulonglong to double... yes, it is that sucky */
|
149
|
+
return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7;
|
150
|
+
}
|
151
|
+
|
152
|
+
#endif
|
153
|
+
|
data/ext/libev/ev_wrap.h
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
/* DO NOT EDIT, automatically generated by update_ev_wrap */
|
2
|
+
#ifndef EV_WRAP_H
|
3
|
+
#define EV_WRAP_H
|
4
|
+
#define now_floor ((loop)->now_floor)
|
5
|
+
#define mn_now ((loop)->mn_now)
|
6
|
+
#define rtmn_diff ((loop)->rtmn_diff)
|
7
|
+
#define io_blocktime ((loop)->io_blocktime)
|
8
|
+
#define timeout_blocktime ((loop)->timeout_blocktime)
|
9
|
+
#define backend ((loop)->backend)
|
10
|
+
#define activecnt ((loop)->activecnt)
|
11
|
+
#define loop_done ((loop)->loop_done)
|
12
|
+
#define backend_fd ((loop)->backend_fd)
|
13
|
+
#define backend_fudge ((loop)->backend_fudge)
|
14
|
+
#define backend_modify ((loop)->backend_modify)
|
15
|
+
#define backend_poll ((loop)->backend_poll)
|
16
|
+
#define anfds ((loop)->anfds)
|
17
|
+
#define anfdmax ((loop)->anfdmax)
|
18
|
+
#define pendings ((loop)->pendings)
|
19
|
+
#define pendingmax ((loop)->pendingmax)
|
20
|
+
#define pendingcnt ((loop)->pendingcnt)
|
21
|
+
#define pending_w ((loop)->pending_w)
|
22
|
+
#define rfeeds ((loop)->rfeeds)
|
23
|
+
#define rfeedmax ((loop)->rfeedmax)
|
24
|
+
#define rfeedcnt ((loop)->rfeedcnt)
|
25
|
+
#define evfd ((loop)->evfd)
|
26
|
+
#define evpipe ((loop)->evpipe)
|
27
|
+
#define pipe_w ((loop)->pipe_w)
|
28
|
+
#define curpid ((loop)->curpid)
|
29
|
+
#define postfork ((loop)->postfork)
|
30
|
+
#define vec_ri ((loop)->vec_ri)
|
31
|
+
#define vec_ro ((loop)->vec_ro)
|
32
|
+
#define vec_wi ((loop)->vec_wi)
|
33
|
+
#define vec_wo ((loop)->vec_wo)
|
34
|
+
#define vec_eo ((loop)->vec_eo)
|
35
|
+
#define vec_max ((loop)->vec_max)
|
36
|
+
#define polls ((loop)->polls)
|
37
|
+
#define pollmax ((loop)->pollmax)
|
38
|
+
#define pollcnt ((loop)->pollcnt)
|
39
|
+
#define pollidxs ((loop)->pollidxs)
|
40
|
+
#define pollidxmax ((loop)->pollidxmax)
|
41
|
+
#define epoll_events ((loop)->epoll_events)
|
42
|
+
#define epoll_eventmax ((loop)->epoll_eventmax)
|
43
|
+
#define epoll_eperms ((loop)->epoll_eperms)
|
44
|
+
#define epoll_epermcnt ((loop)->epoll_epermcnt)
|
45
|
+
#define epoll_epermmax ((loop)->epoll_epermmax)
|
46
|
+
#define kqueue_changes ((loop)->kqueue_changes)
|
47
|
+
#define kqueue_changemax ((loop)->kqueue_changemax)
|
48
|
+
#define kqueue_changecnt ((loop)->kqueue_changecnt)
|
49
|
+
#define kqueue_events ((loop)->kqueue_events)
|
50
|
+
#define kqueue_eventmax ((loop)->kqueue_eventmax)
|
51
|
+
#define port_events ((loop)->port_events)
|
52
|
+
#define port_eventmax ((loop)->port_eventmax)
|
53
|
+
#define iocp ((loop)->iocp)
|
54
|
+
#define fdchanges ((loop)->fdchanges)
|
55
|
+
#define fdchangemax ((loop)->fdchangemax)
|
56
|
+
#define fdchangecnt ((loop)->fdchangecnt)
|
57
|
+
#define timers ((loop)->timers)
|
58
|
+
#define timermax ((loop)->timermax)
|
59
|
+
#define timercnt ((loop)->timercnt)
|
60
|
+
#define periodics ((loop)->periodics)
|
61
|
+
#define periodicmax ((loop)->periodicmax)
|
62
|
+
#define periodiccnt ((loop)->periodiccnt)
|
63
|
+
#define idles ((loop)->idles)
|
64
|
+
#define idlemax ((loop)->idlemax)
|
65
|
+
#define idlecnt ((loop)->idlecnt)
|
66
|
+
#define idleall ((loop)->idleall)
|
67
|
+
#define prepares ((loop)->prepares)
|
68
|
+
#define preparemax ((loop)->preparemax)
|
69
|
+
#define preparecnt ((loop)->preparecnt)
|
70
|
+
#define checks ((loop)->checks)
|
71
|
+
#define checkmax ((loop)->checkmax)
|
72
|
+
#define checkcnt ((loop)->checkcnt)
|
73
|
+
#define forks ((loop)->forks)
|
74
|
+
#define forkmax ((loop)->forkmax)
|
75
|
+
#define forkcnt ((loop)->forkcnt)
|
76
|
+
#define cleanups ((loop)->cleanups)
|
77
|
+
#define cleanupmax ((loop)->cleanupmax)
|
78
|
+
#define cleanupcnt ((loop)->cleanupcnt)
|
79
|
+
#define async_pending ((loop)->async_pending)
|
80
|
+
#define asyncs ((loop)->asyncs)
|
81
|
+
#define asyncmax ((loop)->asyncmax)
|
82
|
+
#define asynccnt ((loop)->asynccnt)
|
83
|
+
#define fs_fd ((loop)->fs_fd)
|
84
|
+
#define fs_w ((loop)->fs_w)
|
85
|
+
#define fs_2625 ((loop)->fs_2625)
|
86
|
+
#define fs_hash ((loop)->fs_hash)
|
87
|
+
#define sig_pending ((loop)->sig_pending)
|
88
|
+
#define nosigmask ((loop)->nosigmask)
|
89
|
+
#define sigfd ((loop)->sigfd)
|
90
|
+
#define sigfd_w ((loop)->sigfd_w)
|
91
|
+
#define sigfd_set ((loop)->sigfd_set)
|
92
|
+
#define origflags ((loop)->origflags)
|
93
|
+
#define loop_count ((loop)->loop_count)
|
94
|
+
#define loop_depth ((loop)->loop_depth)
|
95
|
+
#define userdata ((loop)->userdata)
|
96
|
+
#define release_cb ((loop)->release_cb)
|
97
|
+
#define acquire_cb ((loop)->acquire_cb)
|
98
|
+
#define invoke_cb ((loop)->invoke_cb)
|
99
|
+
#else
|
100
|
+
#undef EV_WRAP_H
|
101
|
+
#undef now_floor
|
102
|
+
#undef mn_now
|
103
|
+
#undef rtmn_diff
|
104
|
+
#undef io_blocktime
|
105
|
+
#undef timeout_blocktime
|
106
|
+
#undef backend
|
107
|
+
#undef activecnt
|
108
|
+
#undef loop_done
|
109
|
+
#undef backend_fd
|
110
|
+
#undef backend_fudge
|
111
|
+
#undef backend_modify
|
112
|
+
#undef backend_poll
|
113
|
+
#undef anfds
|
114
|
+
#undef anfdmax
|
115
|
+
#undef pendings
|
116
|
+
#undef pendingmax
|
117
|
+
#undef pendingcnt
|
118
|
+
#undef pending_w
|
119
|
+
#undef rfeeds
|
120
|
+
#undef rfeedmax
|
121
|
+
#undef rfeedcnt
|
122
|
+
#undef evfd
|
123
|
+
#undef evpipe
|
124
|
+
#undef pipe_w
|
125
|
+
#undef curpid
|
126
|
+
#undef postfork
|
127
|
+
#undef vec_ri
|
128
|
+
#undef vec_ro
|
129
|
+
#undef vec_wi
|
130
|
+
#undef vec_wo
|
131
|
+
#undef vec_eo
|
132
|
+
#undef vec_max
|
133
|
+
#undef polls
|
134
|
+
#undef pollmax
|
135
|
+
#undef pollcnt
|
136
|
+
#undef pollidxs
|
137
|
+
#undef pollidxmax
|
138
|
+
#undef epoll_events
|
139
|
+
#undef epoll_eventmax
|
140
|
+
#undef epoll_eperms
|
141
|
+
#undef epoll_epermcnt
|
142
|
+
#undef epoll_epermmax
|
143
|
+
#undef kqueue_changes
|
144
|
+
#undef kqueue_changemax
|
145
|
+
#undef kqueue_changecnt
|
146
|
+
#undef kqueue_events
|
147
|
+
#undef kqueue_eventmax
|
148
|
+
#undef port_events
|
149
|
+
#undef port_eventmax
|
150
|
+
#undef iocp
|
151
|
+
#undef fdchanges
|
152
|
+
#undef fdchangemax
|
153
|
+
#undef fdchangecnt
|
154
|
+
#undef timers
|
155
|
+
#undef timermax
|
156
|
+
#undef timercnt
|
157
|
+
#undef periodics
|
158
|
+
#undef periodicmax
|
159
|
+
#undef periodiccnt
|
160
|
+
#undef idles
|
161
|
+
#undef idlemax
|
162
|
+
#undef idlecnt
|
163
|
+
#undef idleall
|
164
|
+
#undef prepares
|
165
|
+
#undef preparemax
|
166
|
+
#undef preparecnt
|
167
|
+
#undef checks
|
168
|
+
#undef checkmax
|
169
|
+
#undef checkcnt
|
170
|
+
#undef forks
|
171
|
+
#undef forkmax
|
172
|
+
#undef forkcnt
|
173
|
+
#undef cleanups
|
174
|
+
#undef cleanupmax
|
175
|
+
#undef cleanupcnt
|
176
|
+
#undef async_pending
|
177
|
+
#undef asyncs
|
178
|
+
#undef asyncmax
|
179
|
+
#undef asynccnt
|
180
|
+
#undef fs_fd
|
181
|
+
#undef fs_w
|
182
|
+
#undef fs_2625
|
183
|
+
#undef fs_hash
|
184
|
+
#undef sig_pending
|
185
|
+
#undef nosigmask
|
186
|
+
#undef sigfd
|
187
|
+
#undef sigfd_w
|
188
|
+
#undef sigfd_set
|
189
|
+
#undef origflags
|
190
|
+
#undef loop_count
|
191
|
+
#undef loop_depth
|
192
|
+
#undef userdata
|
193
|
+
#undef release_cb
|
194
|
+
#undef acquire_cb
|
195
|
+
#undef invoke_cb
|
196
|
+
#endif
|
@@ -0,0 +1,123 @@
|
|
1
|
+
// a single header file is required
|
2
|
+
#include <ev.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <io.h>
|
5
|
+
|
6
|
+
// every watcher type has its own typedef'd struct
|
7
|
+
// with the name ev_TYPE
|
8
|
+
ev_io stdin_watcher;
|
9
|
+
ev_timer timeout_watcher;
|
10
|
+
|
11
|
+
// all watcher callbacks have a similar signature
|
12
|
+
// this callback is called when data is readable on stdin
|
13
|
+
static void
|
14
|
+
stdin_cb (EV_P_ ev_io *w, int revents)
|
15
|
+
{
|
16
|
+
puts ("stdin ready or done or something");
|
17
|
+
// for one-shot events, one must manually stop the watcher
|
18
|
+
// with its corresponding stop function.
|
19
|
+
//ev_io_stop (EV_A_ w);
|
20
|
+
|
21
|
+
// this causes all nested ev_loop's to stop iterating
|
22
|
+
//ev_unloop (EV_A_ EVUNLOOP_ALL);
|
23
|
+
}
|
24
|
+
|
25
|
+
// another callback, this time for a time-out
|
26
|
+
static void
|
27
|
+
timeout_cb (EV_P_ ev_timer *w, int revents)
|
28
|
+
{
|
29
|
+
puts ("timeout");
|
30
|
+
// this causes the innermost ev_loop to stop iterating
|
31
|
+
ev_unloop (EV_A_ EVUNLOOP_ONE);
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
#include <winsock.h>
|
37
|
+
|
38
|
+
#include <stdlib.h>
|
39
|
+
#include <iostream>
|
40
|
+
int get_server_fd()
|
41
|
+
{
|
42
|
+
|
43
|
+
//----------------------
|
44
|
+
// Initialize Winsock.
|
45
|
+
WSADATA wsaData;
|
46
|
+
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
47
|
+
if (iResult != NO_ERROR) {
|
48
|
+
printf("Error at WSAStartup()\n");
|
49
|
+
return 1;
|
50
|
+
}
|
51
|
+
|
52
|
+
//----------------------
|
53
|
+
// Create a SOCKET for listening for
|
54
|
+
// incoming connection requests.
|
55
|
+
SOCKET ListenSocket;
|
56
|
+
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
57
|
+
if (ListenSocket == INVALID_SOCKET) {
|
58
|
+
printf("Error at socket(): %ld\n", WSAGetLastError());
|
59
|
+
WSACleanup();
|
60
|
+
return 1;
|
61
|
+
}
|
62
|
+
printf("socket returned %d\n", ListenSocket);
|
63
|
+
|
64
|
+
//----------------------
|
65
|
+
// The sockaddr_in structure specifies the address family,
|
66
|
+
// IP address, and port for the socket that is being bound.
|
67
|
+
sockaddr_in service;
|
68
|
+
service.sin_family = AF_INET;
|
69
|
+
service.sin_addr.s_addr = inet_addr("127.0.0.1");
|
70
|
+
service.sin_port = htons(4444);
|
71
|
+
|
72
|
+
if (bind( ListenSocket,
|
73
|
+
(SOCKADDR*) &service,
|
74
|
+
sizeof(service)) == SOCKET_ERROR) {
|
75
|
+
printf("bind() failed.\n");
|
76
|
+
closesocket(ListenSocket);
|
77
|
+
WSACleanup();
|
78
|
+
return 1;
|
79
|
+
}
|
80
|
+
|
81
|
+
//----------------------
|
82
|
+
// Listen for incoming connection requests.
|
83
|
+
// on the created socket
|
84
|
+
if (listen( ListenSocket, 1 ) == SOCKET_ERROR) {
|
85
|
+
printf("Error listening on socket.\n");
|
86
|
+
closesocket(ListenSocket);
|
87
|
+
WSACleanup();
|
88
|
+
return 1;
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
printf("sock and osf handle are %d %d, error is \n", ListenSocket, _get_osfhandle (ListenSocket)); // -1 is invalid file handle: http://msdn.microsoft.com/en-us/library/ks2530z6.aspx
|
93
|
+
printf("err was %d\n", WSAGetLastError());
|
94
|
+
//----------------------
|
95
|
+
return ListenSocket;
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
int
|
100
|
+
main (void)
|
101
|
+
{
|
102
|
+
struct ev_loop *loopy = ev_default_loop(0);
|
103
|
+
int fd = get_server_fd();
|
104
|
+
int fd_real = _open_osfhandle(fd, NULL);
|
105
|
+
int conv = _get_osfhandle(fd_real);
|
106
|
+
printf("got server fd %d, loop %d, fd_real %d, that converted %d\n", fd, loopy, fd_real, conv);
|
107
|
+
// accept(fd, NULL, NULL);
|
108
|
+
// initialise an io watcher, then start it
|
109
|
+
// this one will watch for stdin to become readable
|
110
|
+
ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ conv, EV_READ);
|
111
|
+
ev_io_start (loopy, &stdin_watcher);
|
112
|
+
|
113
|
+
// initialise a timer watcher, then start it
|
114
|
+
// simple non-repeating 5.5 second timeout
|
115
|
+
//ev_timer_init (&timeout_watcher, timeout_cb, 15.5, 0.);
|
116
|
+
//ev_timer_start (loopy, &timeout_watcher);
|
117
|
+
printf("starting loop\n");
|
118
|
+
// now wait for events to arrive
|
119
|
+
ev_loop (loopy, 0);
|
120
|
+
|
121
|
+
// unloop was called, so exit
|
122
|
+
return 0;
|
123
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
if have_func('rb_thread_blocking_region')
|
4
|
+
$defs << '-DHAVE_RB_THREAD_BLOCKING_REGION'
|
5
|
+
end
|
6
|
+
|
7
|
+
if have_header('sys/select.h')
|
8
|
+
$defs << '-DEV_USE_SELECT'
|
9
|
+
end
|
10
|
+
|
11
|
+
if have_header('poll.h')
|
12
|
+
$defs << '-DEV_USE_POLL'
|
13
|
+
end
|
14
|
+
|
15
|
+
if have_header('sys/epoll.h')
|
16
|
+
$defs << '-DEV_USE_EPOLL'
|
17
|
+
end
|
18
|
+
|
19
|
+
if have_header('sys/event.h') and have_header('sys/queue.h')
|
20
|
+
$defs << '-DEV_USE_KQUEUE'
|
21
|
+
end
|
22
|
+
|
23
|
+
if have_header('port.h')
|
24
|
+
$defs << '-DEV_USE_PORT'
|
25
|
+
end
|
26
|
+
|
27
|
+
if have_header('sys/resource.h')
|
28
|
+
$defs << '-DHAVE_SYS_RESOURCE_H'
|
29
|
+
end
|
30
|
+
|
31
|
+
dir_config 'nio4r_ext'
|
32
|
+
create_makefile 'nio4r_ext'
|
33
|
+
|
34
|
+
# win32 needs to link in "just the right order" for some reason or ioctlsocket will be mapped to an [inverted] ruby specific version.
|
35
|
+
# See libev mailing list for (not so helpful discussion--true cause I'm not sure, but this overcomes the symptom)
|
36
|
+
if RUBY_PLATFORM =~ /mingw|win32/
|
37
|
+
makefile_contents = File.read 'Makefile'
|
38
|
+
|
39
|
+
# "Init_cool could not be found" when loading cool.io.so.
|
40
|
+
makefile_contents.gsub! 'DLDFLAGS = ', 'DLDFLAGS = -export-all '
|
41
|
+
|
42
|
+
makefile_contents.gsub! 'LIBS = $(LIBRUBYARG_SHARED)', 'LIBS = -lws2_32 $(LIBRUBYARG_SHARED)'
|
43
|
+
File.open('Makefile', 'w') { |f| f.write makefile_contents }
|
44
|
+
end
|
data/ext/nio4r/libev.h
ADDED
data/ext/nio4r/monitor.c
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2011 Tony Arcieri. Distributed under the MIT License. See
|
3
|
+
* LICENSE.txt for further details.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "nio4r.h"
|
7
|
+
#include <assert.h>
|
8
|
+
|
9
|
+
static VALUE mNIO = Qnil;
|
10
|
+
static VALUE cNIO_Monitor = Qnil;
|
11
|
+
|
12
|
+
/* Allocator/deallocator */
|
13
|
+
static VALUE NIO_Monitor_allocate(VALUE klass);
|
14
|
+
static void NIO_Monitor_mark(struct NIO_Monitor *monitor);
|
15
|
+
static void NIO_Monitor_free(struct NIO_Monitor *monitor);
|
16
|
+
|
17
|
+
/* Methods */
|
18
|
+
static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector, VALUE io, VALUE interests);
|
19
|
+
static VALUE NIO_Monitor_close(VALUE self);
|
20
|
+
static VALUE NIO_Monitor_is_closed(VALUE self);
|
21
|
+
static VALUE NIO_Monitor_io(VALUE self);
|
22
|
+
static VALUE NIO_Monitor_interests(VALUE self);
|
23
|
+
static VALUE NIO_Monitor_value(VALUE self);
|
24
|
+
static VALUE NIO_Monitor_set_value(VALUE self, VALUE obj);
|
25
|
+
|
26
|
+
/* Internal functions */
|
27
|
+
static void NIO_Monitor_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents);
|
28
|
+
|
29
|
+
#if HAVE_RB_IO_T
|
30
|
+
rb_io_t *fptr;
|
31
|
+
#else
|
32
|
+
OpenFile *fptr;
|
33
|
+
#endif
|
34
|
+
|
35
|
+
/* Monitor control how a channel is being waited for by a monitor */
|
36
|
+
void Init_NIO_Monitor()
|
37
|
+
{
|
38
|
+
mNIO = rb_define_module("NIO");
|
39
|
+
cNIO_Monitor = rb_define_class_under(mNIO, "Monitor", rb_cObject);
|
40
|
+
rb_define_alloc_func(cNIO_Monitor, NIO_Monitor_allocate);
|
41
|
+
|
42
|
+
rb_define_method(cNIO_Monitor, "initialize", NIO_Monitor_initialize, 3);
|
43
|
+
rb_define_method(cNIO_Monitor, "close", NIO_Monitor_close, 0);
|
44
|
+
rb_define_method(cNIO_Monitor, "closed?", NIO_Monitor_is_closed, 0);
|
45
|
+
rb_define_method(cNIO_Monitor, "io", NIO_Monitor_io, 0);
|
46
|
+
rb_define_method(cNIO_Monitor, "interests", NIO_Monitor_interests, 0);
|
47
|
+
rb_define_method(cNIO_Monitor, "value", NIO_Monitor_value, 0);
|
48
|
+
rb_define_method(cNIO_Monitor, "value=", NIO_Monitor_set_value, 1);
|
49
|
+
}
|
50
|
+
|
51
|
+
static VALUE NIO_Monitor_allocate(VALUE klass)
|
52
|
+
{
|
53
|
+
struct NIO_Monitor *monitor = (struct NIO_Monitor *)xmalloc(sizeof(struct NIO_Monitor));
|
54
|
+
|
55
|
+
return Data_Wrap_Struct(klass, NIO_Monitor_mark, NIO_Monitor_free, monitor);
|
56
|
+
}
|
57
|
+
|
58
|
+
static void NIO_Monitor_mark(struct NIO_Monitor *monitor)
|
59
|
+
{
|
60
|
+
}
|
61
|
+
|
62
|
+
static void NIO_Monitor_free(struct NIO_Monitor *monitor)
|
63
|
+
{
|
64
|
+
xfree(monitor);
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector_obj, VALUE io, VALUE interests)
|
68
|
+
{
|
69
|
+
struct NIO_Monitor *monitor;
|
70
|
+
struct NIO_Selector *selector;
|
71
|
+
int events;
|
72
|
+
ID interests_id;
|
73
|
+
|
74
|
+
#if HAVE_RB_IO_T
|
75
|
+
rb_io_t *fptr;
|
76
|
+
#else
|
77
|
+
OpenFile *fptr;
|
78
|
+
#endif
|
79
|
+
|
80
|
+
interests_id = SYM2ID(interests);
|
81
|
+
|
82
|
+
if(interests_id == rb_intern("r")) {
|
83
|
+
events = EV_READ;
|
84
|
+
} else if(interests_id == rb_intern("w")) {
|
85
|
+
events = EV_WRITE;
|
86
|
+
} else if(interests_id == rb_intern("rw")) {
|
87
|
+
events = EV_READ | EV_WRITE;
|
88
|
+
} else {
|
89
|
+
rb_raise(rb_eArgError, "invalid event type %s (must be :r, :w, or :rw)",
|
90
|
+
RSTRING_PTR(rb_funcall(interests, rb_intern("inspect"), 0, 0)));
|
91
|
+
}
|
92
|
+
|
93
|
+
Data_Get_Struct(self, struct NIO_Monitor, monitor);
|
94
|
+
|
95
|
+
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
|
96
|
+
ev_io_init(&monitor->ev_io, NIO_Monitor_callback, FPTR_TO_FD(fptr), events);
|
97
|
+
|
98
|
+
rb_ivar_set(self, rb_intern("selector"), selector_obj);
|
99
|
+
rb_ivar_set(self, rb_intern("io"), io);
|
100
|
+
rb_ivar_set(self, rb_intern("interests"), interests);
|
101
|
+
|
102
|
+
Data_Get_Struct(selector_obj, struct NIO_Selector, selector);
|
103
|
+
|
104
|
+
monitor->self = self;
|
105
|
+
monitor->ev_io.data = (void *)monitor;
|
106
|
+
|
107
|
+
/* We can safely hang onto this as we also hang onto a reference to the
|
108
|
+
object where it originally came from */
|
109
|
+
monitor->selector = selector;
|
110
|
+
|
111
|
+
ev_io_start(selector->ev_loop, &monitor->ev_io);
|
112
|
+
|
113
|
+
return Qnil;
|
114
|
+
}
|
115
|
+
|
116
|
+
static VALUE NIO_Monitor_close(VALUE self)
|
117
|
+
{
|
118
|
+
struct NIO_Monitor *monitor;
|
119
|
+
Data_Get_Struct(self, struct NIO_Monitor, monitor);
|
120
|
+
|
121
|
+
if(monitor->selector) {
|
122
|
+
ev_io_stop(monitor->selector->ev_loop, &monitor->ev_io);
|
123
|
+
monitor->selector = 0;
|
124
|
+
}
|
125
|
+
|
126
|
+
return Qnil;
|
127
|
+
}
|
128
|
+
|
129
|
+
static VALUE NIO_Monitor_is_closed(VALUE self)
|
130
|
+
{
|
131
|
+
struct NIO_Monitor *monitor;
|
132
|
+
Data_Get_Struct(self, struct NIO_Monitor, monitor);
|
133
|
+
|
134
|
+
return !monitor->selector;
|
135
|
+
}
|
136
|
+
|
137
|
+
static VALUE NIO_Monitor_io(VALUE self)
|
138
|
+
{
|
139
|
+
return rb_ivar_get(self, rb_intern("io"));
|
140
|
+
}
|
141
|
+
|
142
|
+
static VALUE NIO_Monitor_interests(VALUE self)
|
143
|
+
{
|
144
|
+
return rb_ivar_get(self, rb_intern("interests"));
|
145
|
+
}
|
146
|
+
|
147
|
+
static VALUE NIO_Monitor_value(VALUE self)
|
148
|
+
{
|
149
|
+
return rb_ivar_get(self, rb_intern("value"));
|
150
|
+
}
|
151
|
+
|
152
|
+
static VALUE NIO_Monitor_set_value(VALUE self, VALUE obj)
|
153
|
+
{
|
154
|
+
return rb_ivar_set(self, rb_intern("value"), obj);
|
155
|
+
}
|
156
|
+
|
157
|
+
/* libev callback fired whenever this monitor gets events */
|
158
|
+
static void NIO_Monitor_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents)
|
159
|
+
{
|
160
|
+
struct NIO_Monitor *monitor = (struct NIO_Monitor *)io->data;
|
161
|
+
|
162
|
+
assert(monitor->selector != 0);
|
163
|
+
NIO_Selector_handle_event(monitor->selector, monitor->self, revents);
|
164
|
+
}
|