packet 0.1.0 → 0.1.1
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/MIT-LICENSE +20 -0
- data/README +4 -0
- data/Rakefile +16 -8
- data/TODO +8 -0
- data/examples/asteroid.c +296 -0
- data/examples/asteroid.h +5 -0
- data/examples/concurrent_thread.c +53 -0
- data/examples/extconf.h +4 -0
- data/examples/extconf.rb +10 -0
- data/examples/persistent_print.rb +24 -0
- data/examples/sample_server.rb +19 -0
- data/examples/use_stuff.rb +3 -0
- data/lib/bin_parser.rb +16 -8
- data/lib/class_helpers.rb +74 -0
- data/lib/connection.rb +18 -18
- data/lib/core.rb +38 -13
- data/lib/double_keyed_hash.rb +6 -0
- data/lib/meta_pimp.rb +20 -6
- data/lib/nbio.rb +27 -30
- data/lib/packet.rb +6 -6
- data/lib/packet_master.rb +55 -58
- data/lib/pimp.rb +1 -0
- data/lib/thread_pool.rb +54 -0
- data/lib/timer_store.rb +63 -0
- data/lib/worker.rb +4 -28
- data/lib/worker_pool.rb +10 -0
- metadata +66 -55
- data/LICENSE +0 -4
- data/bin/packet_mongrel.rb +0 -215
- data/bin/runner.rb +0 -35
- data/lib/attribute_accessors.rb +0 -48
- data/lib/buftok.rb +0 -127
- data/lib/cpu_worker.rb +0 -19
- data/lib/deferrable.rb +0 -210
- data/lib/io_worker.rb +0 -6
- data/lib/ruby_hacks.rb +0 -125
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2004-2007 Hemant Kumar
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
CHANGED
@@ -242,6 +242,10 @@ end
|
|
242
242
|
reasonably well. Mongrel, running on top of Packet is a tad
|
243
243
|
slower than Mongrel running on top of EventMachine. More benchmarks coming soon.
|
244
244
|
|
245
|
+
== SVN repo:
|
246
|
+
Code for packet is on google code, svn repo is:
|
247
|
+
http://packet.googlecode.com/svn/trunk/
|
248
|
+
|
245
249
|
== Credits
|
246
250
|
Francis for awesome EventMachine lib, which has constantly acted as an inspiration.
|
247
251
|
Ezra, for being a early user and porting mongrel to run on top of packet
|
data/Rakefile
CHANGED
@@ -6,6 +6,7 @@ require 'rake/rdoctask'
|
|
6
6
|
require 'rake/testtask'
|
7
7
|
require 'spec/rake/spectask'
|
8
8
|
require 'fileutils'
|
9
|
+
|
9
10
|
def __DIR__
|
10
11
|
File.dirname(__FILE__)
|
11
12
|
end
|
@@ -31,7 +32,7 @@ task :doc => [:rdoc]
|
|
31
32
|
|
32
33
|
|
33
34
|
Rake::RDocTask.new do |rdoc|
|
34
|
-
files = ['README', 'LICENSE', 'CHANGELOG',
|
35
|
+
files = ['README', 'MIT-LICENSE', 'CHANGELOG',
|
35
36
|
'lib/**/*.rb']
|
36
37
|
rdoc.rdoc_files.add(files)
|
37
38
|
rdoc.main = 'README'
|
@@ -45,20 +46,19 @@ spec = Gem::Specification.new do |s|
|
|
45
46
|
s.version = Packet::VERSION
|
46
47
|
s.platform = Gem::Platform::RUBY
|
47
48
|
s.has_rdoc = true
|
48
|
-
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
49
|
+
s.extra_rdoc_files = ["README", "MIT-LICENSE", 'TODO']
|
49
50
|
#s.rdoc_options += RDOC_OPTS +
|
50
51
|
# ['--exclude', '^(app|uploads)']
|
51
|
-
s.summary = "Packet,
|
52
|
+
s.summary = "Packet, A Pure Ruby library for Event Driven Network Programming."
|
52
53
|
s.description = s.summary
|
53
|
-
s.author = "Hemant"
|
54
|
-
s.email = '
|
54
|
+
s.author = "Hemant Kumar"
|
55
|
+
s.email = 'mail@gnufied.org'
|
55
56
|
s.homepage = 'http://code.google.com/p/packet/'
|
56
|
-
s.required_ruby_version = '>= 1.8.
|
57
|
+
s.required_ruby_version = '>= 1.8.5'
|
57
58
|
|
58
|
-
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{
|
59
|
+
s.files = %w(MIT-LICENSE README Rakefile TODO) + Dir.glob("{spec,lib,examples}/**/*")
|
59
60
|
|
60
61
|
s.require_path = "lib"
|
61
|
-
s.bindir = "bin"
|
62
62
|
end
|
63
63
|
|
64
64
|
Rake::GemPackageTask.new(spec) do |p|
|
@@ -85,3 +85,11 @@ task :svn_add do
|
|
85
85
|
end
|
86
86
|
|
87
87
|
|
88
|
+
desc "Converts a YAML file into a test/spec skeleton"
|
89
|
+
task :yaml_to_spec do
|
90
|
+
require 'yaml'
|
91
|
+
|
92
|
+
puts YAML.load_file(ENV['FILE']||!puts("Pass in FILE argument.")&&exit).inject(''){|t,(c,s)|
|
93
|
+
t+(s ?%.context "#{c}" do.+s.map{|d|%.\n xspecify "#{d}" do\n end\n.}*''+"end\n\n":'')
|
94
|
+
}.strip
|
95
|
+
end
|
data/TODO
CHANGED
@@ -0,0 +1,8 @@
|
|
1
|
+
* Overview *
|
2
|
+
** TODO Implement ability to have a pool of workers.
|
3
|
+
** TODO Remove class and class instance attributes from core classes.
|
4
|
+
** TODO Cleanup callback mechanism
|
5
|
+
** TODO Implement a sample worker, which provides capabilities to execute mysql statements async.
|
6
|
+
|
7
|
+
|
8
|
+
|
data/examples/asteroid.c
ADDED
@@ -0,0 +1,296 @@
|
|
1
|
+
/* --------------------------------------------------------------------------
|
2
|
+
* Asteroid ruby extension.
|
3
|
+
* by Genki Takiuchi <takiuchi@drecom.co.jp>
|
4
|
+
* -------------------------------------------------------------------------- */
|
5
|
+
#include <ruby.h>
|
6
|
+
#include <rubysig.h>
|
7
|
+
#include <unistd.h>
|
8
|
+
#include <fcntl.h>
|
9
|
+
#include <errno.h>
|
10
|
+
#include <sys/types.h>
|
11
|
+
#include <sys/socket.h>
|
12
|
+
#include <sys/time.h>
|
13
|
+
#include <netinet/in.h>
|
14
|
+
#include <arpa/inet.h>
|
15
|
+
#include "extconf.h"
|
16
|
+
#include "asteroid.h"
|
17
|
+
|
18
|
+
/* --------------------------------------------------------------------------
|
19
|
+
* epoll / kqueue
|
20
|
+
* - 2007/03/09 *BSD kqueue port, Mac OS X MSG_NOSIGNAL missing.
|
21
|
+
* (Takanori Ishikawa)
|
22
|
+
* -------------------------------------------------------------------------- */
|
23
|
+
#ifdef HAVE_SYS_EVENT_H
|
24
|
+
#include <sys/event.h>
|
25
|
+
typedef int asteroid_pollfd_t;
|
26
|
+
typedef struct kevent asteroid_poll_event_t;
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#ifdef HAVE_SYS_EPOLL_H
|
30
|
+
#include <sys/epoll.h>
|
31
|
+
typedef int asteroid_pollfd_t;
|
32
|
+
typedef struct epoll_event asteroid_poll_event_t;
|
33
|
+
#endif
|
34
|
+
|
35
|
+
static asteroid_pollfd_t asteroid_poll_create(int sizeHint) {
|
36
|
+
#ifdef HAVE_SYS_EVENT_H
|
37
|
+
return kqueue();
|
38
|
+
#endif
|
39
|
+
#ifdef HAVE_SYS_EPOLL_H
|
40
|
+
return epoll_create(sizeHint);
|
41
|
+
#endif
|
42
|
+
}
|
43
|
+
|
44
|
+
static int asteroid_poll_add(
|
45
|
+
asteroid_pollfd_t pollfd,
|
46
|
+
asteroid_poll_event_t *event,
|
47
|
+
int fd) {
|
48
|
+
#ifdef HAVE_SYS_EVENT_H
|
49
|
+
EV_SET(event, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
50
|
+
return kevent(pollfd, event, 1, NULL, 0, NULL);
|
51
|
+
#endif
|
52
|
+
#ifdef HAVE_SYS_EPOLL_H
|
53
|
+
event->events = (EPOLLIN | EPOLLPRI);
|
54
|
+
event->data.fd = fd;
|
55
|
+
return epoll_ctl(pollfd, EPOLL_CTL_ADD, fd, event);
|
56
|
+
#endif
|
57
|
+
}
|
58
|
+
|
59
|
+
static int asteroid_poll_remove(
|
60
|
+
asteroid_pollfd_t pollfd,
|
61
|
+
asteroid_poll_event_t *event,
|
62
|
+
int fd) {
|
63
|
+
#ifdef HAVE_SYS_EVENT_H
|
64
|
+
EV_SET(event, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
65
|
+
return kevent(pollfd, event, 1, NULL, 0, NULL);
|
66
|
+
#endif
|
67
|
+
#ifdef HAVE_SYS_EPOLL_H
|
68
|
+
return epoll_ctl(pollfd, EPOLL_CTL_DEL, fd, event);
|
69
|
+
#endif
|
70
|
+
}
|
71
|
+
|
72
|
+
static int asteroid_poll_wait(
|
73
|
+
asteroid_pollfd_t pollfd,
|
74
|
+
asteroid_poll_event_t *events,
|
75
|
+
int maxevents,
|
76
|
+
int timeout) {
|
77
|
+
#ifdef HAVE_SYS_EVENT_H
|
78
|
+
struct timespec tv, *tvptr;
|
79
|
+
if (timeout < 0) {
|
80
|
+
tvptr = NULL;
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
tv.tv_sec = (long) (timeout/1000);
|
84
|
+
tv.tv_nsec = (long) (timeout%1000)*1000;
|
85
|
+
tvptr = &tv;
|
86
|
+
}
|
87
|
+
return kevent(pollfd, NULL, 0, events, maxevents, tvptr);
|
88
|
+
#endif
|
89
|
+
#ifdef HAVE_SYS_EPOLL_H
|
90
|
+
return epoll_wait(pollfd, events, maxevents, timeout);
|
91
|
+
#endif
|
92
|
+
}
|
93
|
+
|
94
|
+
#ifdef HAVE_SYS_EVENT_H
|
95
|
+
#define AST_POLL_EVENT_SOCK(event) ((event)->ident)
|
96
|
+
#define AST_POLL_EVENT_CAN_READ(event) ((event)->filter == EVFILT_READ)
|
97
|
+
#endif
|
98
|
+
#ifdef HAVE_SYS_EPOLL_H
|
99
|
+
#define AST_POLL_EVENT_SOCK(event) ((event)->data.fd)
|
100
|
+
#define AST_POLL_EVENT_CAN_READ(event) ((event)->events & (EPOLLIN|EPOLLPRI))
|
101
|
+
#endif
|
102
|
+
|
103
|
+
#ifdef SO_NOSIGPIPE
|
104
|
+
#ifndef MSG_NOSIGNAL
|
105
|
+
#define MSG_NOSIGNAL 0
|
106
|
+
#endif
|
107
|
+
|
108
|
+
/*
|
109
|
+
* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
|
110
|
+
* sending data to a dead peer (instead of relying on the 4th argument to send
|
111
|
+
* being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
|
112
|
+
* systems?
|
113
|
+
*
|
114
|
+
* curl-7.15.5/lib/connect.c
|
115
|
+
*/
|
116
|
+
|
117
|
+
static void nosigpipe(int sockfd) {
|
118
|
+
int one = 1;
|
119
|
+
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(one));
|
120
|
+
}
|
121
|
+
#else
|
122
|
+
#define nosigpipe(x)
|
123
|
+
#endif
|
124
|
+
|
125
|
+
#define MAX_CONNECTION (102400)
|
126
|
+
#define EVENT_BUF_SIZE (1024)
|
127
|
+
|
128
|
+
static VALUE Asteroid;
|
129
|
+
static VALUE clients;
|
130
|
+
static volatile int running = 0;
|
131
|
+
static asteroid_pollfd_t epoll_fd = 0;
|
132
|
+
static asteroid_poll_event_t events[EVENT_BUF_SIZE];
|
133
|
+
|
134
|
+
int dispatch();
|
135
|
+
void runtime_error();
|
136
|
+
|
137
|
+
void Init_asteroid(){
|
138
|
+
Asteroid = rb_define_module("Asteroid");
|
139
|
+
rb_define_singleton_method(Asteroid, "run", asteroid_s_run, 3);
|
140
|
+
rb_define_singleton_method(Asteroid, "stop", asteroid_s_stop, 0);
|
141
|
+
rb_define_singleton_method(Asteroid, "now", asteroid_s_now, 0);
|
142
|
+
rb_define_class_variable(Asteroid, "@@clients", clients = rb_hash_new());
|
143
|
+
}
|
144
|
+
|
145
|
+
static VALUE close_socket_proc(VALUE Pair, VALUE Arg, VALUE Self) {
|
146
|
+
close(FIX2INT(RARRAY(Pair)->ptr[0]));
|
147
|
+
return Qnil;
|
148
|
+
}
|
149
|
+
|
150
|
+
static VALUE asteroid_s_run(VALUE Self, VALUE Host, VALUE Port, VALUE Module){
|
151
|
+
char *host = StringValuePtr(Host);
|
152
|
+
int port = FIX2INT(Port);
|
153
|
+
|
154
|
+
epoll_fd = asteroid_poll_create(1024);
|
155
|
+
if(epoll_fd == -1) runtime_error();
|
156
|
+
|
157
|
+
struct sockaddr_in addr;
|
158
|
+
addr.sin_family = AF_INET;
|
159
|
+
addr.sin_port = htons(port);
|
160
|
+
addr.sin_addr.s_addr = inet_addr(host);
|
161
|
+
int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP), c, one = 1;
|
162
|
+
if(s == -1) runtime_error();
|
163
|
+
fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK);
|
164
|
+
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
|
165
|
+
nosigpipe(s);
|
166
|
+
if(bind(s, (struct sockaddr*)&addr, sizeof(addr)) != 0) runtime_error();
|
167
|
+
if(listen(s, MAX_CONNECTION) != 0) runtime_error();
|
168
|
+
if(rb_block_given_p()) rb_yield(Qnil);
|
169
|
+
|
170
|
+
VALUE Class = rb_define_class_under(Asteroid, "Server", rb_cObject);
|
171
|
+
rb_define_method(Class, "send_data",
|
172
|
+
asteroid_server_send_data, 1);
|
173
|
+
rb_define_method(Class, "write_and_close",
|
174
|
+
asteroid_server_write_and_close, 0);
|
175
|
+
rb_include_module(Class, Module);
|
176
|
+
// Mac OS X, Fedora needs explicit rb_thread_schedule call.
|
177
|
+
for(running = 1; running; rb_thread_schedule()){
|
178
|
+
socklen_t len = sizeof(addr);
|
179
|
+
while((c = accept(s, (struct sockaddr*)&addr, &len)) != -1){
|
180
|
+
printf("A New client connected here\n");
|
181
|
+
fcntl(c, F_SETFL, fcntl(c, F_GETFL, 0) | O_NONBLOCK);
|
182
|
+
asteroid_poll_event_t event;
|
183
|
+
memset(&event, 0, sizeof(event));
|
184
|
+
if(asteroid_poll_add(epoll_fd, &event, c) == -1) runtime_error();
|
185
|
+
// instantiate server class which responds to client.
|
186
|
+
VALUE Server = rb_class_new_instance(0, NULL, Class);
|
187
|
+
rb_iv_set(Server, "@fd", rb_fix_new(c));
|
188
|
+
rb_hash_aset(clients, rb_fix_new(c), Server);
|
189
|
+
if(rb_respond_to(Server, rb_intern("post_init"))){
|
190
|
+
rb_funcall(Server, rb_intern("post_init"), 0);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
if(dispatch() != 0) asteroid_s_stop(Asteroid);
|
194
|
+
// You must call them to give a chance for ruby to handle system events.
|
195
|
+
// CHECK_INTS;
|
196
|
+
}
|
197
|
+
|
198
|
+
rb_iterate(rb_each, clients, close_socket_proc, Qnil);
|
199
|
+
rb_funcall(clients, rb_intern("clear"), 0);
|
200
|
+
close(s);
|
201
|
+
close(epoll_fd);
|
202
|
+
return Qnil;
|
203
|
+
}
|
204
|
+
|
205
|
+
static VALUE asteroid_s_stop(VALUE Self){
|
206
|
+
running = 0;
|
207
|
+
return Qnil;
|
208
|
+
}
|
209
|
+
|
210
|
+
static VALUE asteroid_s_now(VALUE Self){
|
211
|
+
struct timeval now;
|
212
|
+
gettimeofday(&now, NULL);
|
213
|
+
return rb_float_new(now.tv_sec + now.tv_usec/1000000.0);
|
214
|
+
}
|
215
|
+
|
216
|
+
static VALUE asteroid_server_send_data(VALUE Self, VALUE Data){
|
217
|
+
VALUE Fd = rb_iv_get(Self, "@fd");
|
218
|
+
int fd = FIX2INT(Fd), remain = RSTRING(Data)->as.heap.len, len, trial = 100;
|
219
|
+
char *data = StringValuePtr(Data);
|
220
|
+
while(remain){
|
221
|
+
len = send(fd, data, remain, MSG_DONTWAIT|MSG_NOSIGNAL);
|
222
|
+
if(len == -1){
|
223
|
+
if(errno == EAGAIN && --trial){
|
224
|
+
rb_thread_schedule();
|
225
|
+
// CHECK_INTS;
|
226
|
+
}else{
|
227
|
+
if(rb_respond_to(Self, rb_intern("unbind"))){
|
228
|
+
rb_funcall(Self, rb_intern("unbind"), 0);
|
229
|
+
}
|
230
|
+
return Qnil;
|
231
|
+
}
|
232
|
+
}else{
|
233
|
+
remain -= len;
|
234
|
+
data += len;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
return Qtrue;
|
238
|
+
}
|
239
|
+
|
240
|
+
static VALUE asteroid_server_write_and_close(VALUE Self){
|
241
|
+
VALUE Fd = rb_iv_get(Self, "@fd");
|
242
|
+
int fd = FIX2INT(Fd);
|
243
|
+
char buf[1];
|
244
|
+
if(read(fd, buf, 1) == -1 && errno != EAGAIN){
|
245
|
+
if(rb_respond_to(Self, rb_intern("unbind"))){
|
246
|
+
rb_funcall(Self, rb_intern("unbind"), 0);
|
247
|
+
}
|
248
|
+
}
|
249
|
+
asteroid_poll_event_t event;
|
250
|
+
memset(&event, 0, sizeof(event));
|
251
|
+
asteroid_poll_remove(epoll_fd, &event, fd);
|
252
|
+
close(fd);
|
253
|
+
rb_hash_delete(clients, Fd);
|
254
|
+
return Qnil;
|
255
|
+
}
|
256
|
+
|
257
|
+
int dispatch(){
|
258
|
+
int i, s, len;
|
259
|
+
while(1){
|
260
|
+
TRAP_BEG;
|
261
|
+
s = asteroid_poll_wait(epoll_fd, events, EVENT_BUF_SIZE, 1);
|
262
|
+
TRAP_END;
|
263
|
+
if(s <= 0) break;
|
264
|
+
for(i = 0; i < s; ++i){
|
265
|
+
asteroid_poll_event_t event = events[i];
|
266
|
+
int fd = AST_POLL_EVENT_SOCK(&event);
|
267
|
+
VALUE Fd = rb_fix_new(fd);
|
268
|
+
VALUE Server = rb_hash_aref(clients, Fd);
|
269
|
+
if(AST_POLL_EVENT_CAN_READ(&event)){
|
270
|
+
VALUE Buf = rb_str_new("", 0);
|
271
|
+
char buf[1024];
|
272
|
+
while((len = read(fd, buf, 1023)) > 0){
|
273
|
+
buf[len] = '\0';
|
274
|
+
rb_str_concat(Buf, rb_str_new2(buf));
|
275
|
+
}
|
276
|
+
if(len == -1 && errno == EAGAIN){
|
277
|
+
if(rb_respond_to(Server, rb_intern("receive_data"))){
|
278
|
+
rb_funcall(Server, rb_intern("receive_data"), 1, Buf);
|
279
|
+
}
|
280
|
+
}else{
|
281
|
+
if(rb_respond_to(Server, rb_intern("unbind"))){
|
282
|
+
rb_funcall(Server, rb_intern("unbind"), 0);
|
283
|
+
}
|
284
|
+
asteroid_poll_remove(epoll_fd, &event, fd);
|
285
|
+
rb_hash_delete(clients, Fd);
|
286
|
+
close(fd);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
}
|
290
|
+
}
|
291
|
+
return 0;
|
292
|
+
}
|
293
|
+
|
294
|
+
void runtime_error(){
|
295
|
+
rb_raise(rb_eRuntimeError, strerror(errno));
|
296
|
+
}
|
data/examples/asteroid.h
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
static VALUE asteroid_s_run(VALUE Self, VALUE Host, VALUE Port, VALUE Module);
|
2
|
+
static VALUE asteroid_s_stop(VALUE Self);
|
3
|
+
static VALUE asteroid_s_now(VALUE Self);
|
4
|
+
static VALUE asteroid_server_send_data(VALUE Self, VALUE Data);
|
5
|
+
static VALUE asteroid_server_write_and_close(VALUE Self);
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <rubysig.h>
|
3
|
+
#include <unistd.h>
|
4
|
+
#include <fcntl.h>
|
5
|
+
#include <errno.h>
|
6
|
+
#include <sys/types.h>
|
7
|
+
#include <sys/socket.h>
|
8
|
+
#include <sys/time.h>
|
9
|
+
#include <netinet/in.h>
|
10
|
+
#include <arpa/inet.h>
|
11
|
+
|
12
|
+
static VALUE ConcurrentThread;
|
13
|
+
static VALUE ConcurrentThreadPool;
|
14
|
+
|
15
|
+
static void count_to_10000(void* data){
|
16
|
+
int i = 0;
|
17
|
+
for( i = 0; i < 10000; i++ ) {
|
18
|
+
if ((*(VALUE *)data) == Qtrue) break;
|
19
|
+
printf("Currently Counting from thr 1: %d\n",i);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
static void count_to_20000(void* data){
|
24
|
+
int i = 0;
|
25
|
+
for( i = 0; i < 10000; i++ ) {
|
26
|
+
if ((*(VALUE *)data) == Qtrue) break;
|
27
|
+
printf("Currently Counting from thr 2: %d\n",i);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
static void stop_thr1(void* data) {
|
32
|
+
printf("Calling thread1 break method\n");
|
33
|
+
*((VALUE *)data) = Qtrue;
|
34
|
+
}
|
35
|
+
|
36
|
+
static void stop_thr2(void* data) {
|
37
|
+
printf("Calling thread2 break method\n");
|
38
|
+
*((VALUE *)data) = Qtrue;
|
39
|
+
}
|
40
|
+
|
41
|
+
static VALUE rb_concurrent_thread_method(VALUE self)
|
42
|
+
{
|
43
|
+
VALUE interrupt_flag;
|
44
|
+
VALUE interrupt_flag2;
|
45
|
+
rb_thread_blocking_region(count_to_10000,&interrupt_flag,stop_thr1,&interrupt_flag);
|
46
|
+
rb_thread_blocking_region(count_to_20000,&interrupt_flag2,stop_thr2,&interrupt_flag2);
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
void Init_concurrent_thread(){
|
51
|
+
ConcurrentThread = rb_define_class("ConcurrentThread",rb_cObject);
|
52
|
+
rb_define_method(ConcurrentThread,"defer",rb_concurrent_thread_method,0);
|
53
|
+
}
|