cool.io 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +26 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +4 -0
  4. data/{CHANGES → CHANGES.md} +43 -79
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +32 -0
  7. data/{README.markdown → README.md} +0 -4
  8. data/Rakefile +31 -67
  9. data/cool.io.gemspec +25 -133
  10. data/ext/cool.io/extconf.rb +3 -0
  11. data/ext/cool.io/stat_watcher.c +99 -23
  12. data/ext/libev/Changes +24 -0
  13. data/ext/libev/ev.c +78 -32
  14. data/ext/libev/ev.h +11 -8
  15. data/ext/libev/ev_epoll.c +39 -7
  16. data/ext/libev/ev_kqueue.c +5 -5
  17. data/ext/libev/ev_poll.c +5 -5
  18. data/ext/libev/ev_port.c +26 -11
  19. data/ext/libev/ev_select.c +11 -8
  20. data/ext/libev/ev_vars.h +10 -4
  21. data/ext/libev/ev_win32.c +6 -6
  22. data/ext/libev/ev_wrap.h +10 -0
  23. data/lib/cool.io.rb +3 -3
  24. data/lib/cool.io/async_watcher.rb +1 -1
  25. data/lib/cool.io/dns_resolver.rb +14 -12
  26. data/lib/cool.io/dsl.rb +26 -26
  27. data/lib/cool.io/eventmachine.rb +18 -18
  28. data/lib/cool.io/http_client.rb +29 -22
  29. data/lib/cool.io/io.rb +18 -18
  30. data/lib/cool.io/iowatcher.rb +1 -1
  31. data/lib/cool.io/listener.rb +2 -2
  32. data/lib/cool.io/loop.rb +12 -12
  33. data/lib/cool.io/meta.rb +4 -4
  34. data/lib/cool.io/server.rb +3 -3
  35. data/lib/cool.io/socket.rb +36 -28
  36. data/lib/cool.io/timer_watcher.rb +1 -1
  37. data/lib/cool.io/version.rb +5 -0
  38. data/lib/coolio.rb +1 -1
  39. data/spec/stat_watcher_spec.rb +77 -0
  40. metadata +47 -56
  41. data/VERSION +0 -1
  42. data/lib/rev.rb +0 -4
  43. data/spec/possible_tests/schedules_other_threads.rb +0 -48
  44. data/spec/possible_tests/test_on_resolve_failed.rb +0 -9
  45. data/spec/possible_tests/test_resolves.rb +0 -27
  46. data/spec/possible_tests/test_write_during_resolve.rb +0 -27
  47. data/spec/possible_tests/works_straight.rb +0 -71
@@ -1,138 +1,30 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
1
  # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cool.io/version"
5
4
 
6
- Gem::Specification.new do |s|
7
- s.name = %q{cool.io}
8
- s.version = "1.0.0"
5
+ module Cool
6
+ # Allow Coolio module to be referenced as Cool.io
7
+ def self.io; Coolio; end
8
+ end
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Tony Arcieri"]
12
- s.date = %q{2010-12-13}
13
- s.description = %q{A Ruby wrapper around the libev high performance event library}
14
- s.email = %q{tony@medioh.com}
10
+ Gem::Specification.new do |s|
11
+ s.name = "cool.io"
12
+ s.version = Coolio::VERSION
13
+ s.authors = ["Tony Arcieri"]
14
+ s.email = ["tony.arcieri@gmail.com"]
15
+ s.homepage = "http://coolio.github.com"
16
+ s.summary = "A cool framework for doing high performance I/O in Ruby"
17
+ s.description = "Cool.io provides a high performance event framework for Ruby which uses the libev C library"
15
18
  s.extensions = ["ext/cool.io/extconf.rb", "ext/http11_client/extconf.rb"]
16
- s.extra_rdoc_files = [
17
- "LICENSE",
18
- "README.markdown"
19
- ]
20
- s.files = [
21
- "CHANGES",
22
- "LICENSE",
23
- "README.markdown",
24
- "Rakefile",
25
- "VERSION",
26
- "cool.io.gemspec",
27
- "examples/dslified_echo_client.rb",
28
- "examples/dslified_echo_server.rb",
29
- "examples/echo_client.rb",
30
- "examples/echo_server.rb",
31
- "examples/google.rb",
32
- "examples/httpclient.rb",
33
- "ext/cool.io/.gitignore",
34
- "ext/cool.io/cool.io.h",
35
- "ext/cool.io/cool.io_ext.c",
36
- "ext/cool.io/ev_wrap.h",
37
- "ext/cool.io/extconf.rb",
38
- "ext/cool.io/iowatcher.c",
39
- "ext/cool.io/libev.c",
40
- "ext/cool.io/loop.c",
41
- "ext/cool.io/stat_watcher.c",
42
- "ext/cool.io/timer_watcher.c",
43
- "ext/cool.io/utils.c",
44
- "ext/cool.io/watcher.c",
45
- "ext/cool.io/watcher.h",
46
- "ext/http11_client/.gitignore",
47
- "ext/http11_client/LICENSE",
48
- "ext/http11_client/ext_help.h",
49
- "ext/http11_client/extconf.rb",
50
- "ext/http11_client/http11_client.c",
51
- "ext/http11_client/http11_parser.c",
52
- "ext/http11_client/http11_parser.h",
53
- "ext/http11_client/http11_parser.rl",
54
- "ext/libev/Changes",
55
- "ext/libev/LICENSE",
56
- "ext/libev/README",
57
- "ext/libev/README.embed",
58
- "ext/libev/ev.c",
59
- "ext/libev/ev.h",
60
- "ext/libev/ev_epoll.c",
61
- "ext/libev/ev_kqueue.c",
62
- "ext/libev/ev_poll.c",
63
- "ext/libev/ev_port.c",
64
- "ext/libev/ev_select.c",
65
- "ext/libev/ev_vars.h",
66
- "ext/libev/ev_win32.c",
67
- "ext/libev/ev_wrap.h",
68
- "ext/libev/test_libev_win32.c",
69
- "lib/.gitignore",
70
- "lib/cool.io.rb",
71
- "lib/cool.io/async_watcher.rb",
72
- "lib/cool.io/dns_resolver.rb",
73
- "lib/cool.io/dsl.rb",
74
- "lib/cool.io/eventmachine.rb",
75
- "lib/cool.io/http_client.rb",
76
- "lib/cool.io/io.rb",
77
- "lib/cool.io/iowatcher.rb",
78
- "lib/cool.io/listener.rb",
79
- "lib/cool.io/loop.rb",
80
- "lib/cool.io/meta.rb",
81
- "lib/cool.io/server.rb",
82
- "lib/cool.io/socket.rb",
83
- "lib/cool.io/timer_watcher.rb",
84
- "lib/coolio.rb",
85
- "lib/rev.rb",
86
- "spec/async_watcher_spec.rb",
87
- "spec/dns_spec.rb",
88
- "spec/possible_tests/schedules_other_threads.rb",
89
- "spec/possible_tests/test_on_resolve_failed.rb",
90
- "spec/possible_tests/test_resolves.rb",
91
- "spec/possible_tests/test_write_during_resolve.rb",
92
- "spec/possible_tests/works_straight.rb",
93
- "spec/spec_helper.rb",
94
- "spec/timer_watcher_spec.rb",
95
- "spec/unix_listener_spec.rb",
96
- "spec/unix_server_spec.rb"
97
- ]
98
- s.homepage = %q{http://github.com/tarcieri/cool.io}
99
- s.require_paths = ["lib"]
100
- s.rubygems_version = %q{1.3.7}
101
- s.summary = %q{The cool event framework for Ruby}
102
- s.test_files = [
103
- "examples/dslified_echo_client.rb",
104
- "examples/dslified_echo_server.rb",
105
- "examples/echo_client.rb",
106
- "examples/echo_server.rb",
107
- "examples/google.rb",
108
- "examples/httpclient.rb",
109
- "spec/async_watcher_spec.rb",
110
- "spec/dns_spec.rb",
111
- "spec/possible_tests/schedules_other_threads.rb",
112
- "spec/possible_tests/test_on_resolve_failed.rb",
113
- "spec/possible_tests/test_resolves.rb",
114
- "spec/possible_tests/test_write_during_resolve.rb",
115
- "spec/possible_tests/works_straight.rb",
116
- "spec/spec_helper.rb",
117
- "spec/timer_watcher_spec.rb",
118
- "spec/unix_listener_spec.rb",
119
- "spec/unix_server_spec.rb"
120
- ]
121
-
122
- if s.respond_to? :specification_version then
123
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
124
- s.specification_version = 3
125
-
126
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
127
- s.add_runtime_dependency(%q<iobuffer>, [">= 0.1.3"])
128
- s.add_development_dependency(%q<rspec>, [">= 2.1.0"])
129
- else
130
- s.add_dependency(%q<iobuffer>, [">= 0.1.3"])
131
- s.add_dependency(%q<rspec>, [">= 2.1.0"])
132
- end
133
- else
134
- s.add_dependency(%q<iobuffer>, [">= 0.1.3"])
135
- s.add_dependency(%q<rspec>, [">= 2.1.0"])
136
- end
137
- end
138
19
 
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+
25
+ s.add_dependency "iobuffer", ">= 1.0.0"
26
+
27
+ s.add_development_dependency "rake-compiler", "~> 0.7.9"
28
+ s.add_development_dependency "rspec", ">= 2.6.0"
29
+ s.add_development_dependency "rdoc", ">= 3.6.0"
30
+ end
@@ -63,6 +63,9 @@ create_makefile('cool.io_ext')
63
63
  if RUBY_PLATFORM =~ /mingw|win32/
64
64
  makefile_contents = File.read 'Makefile'
65
65
 
66
+ # "Init_cool could not be found" when loading cool.io.so.
67
+ makefile_contents.gsub! 'DLDFLAGS = ', 'DLDFLAGS = -export-all '
68
+
66
69
  makefile_contents.gsub! 'LIBS = $(LIBRUBYARG_SHARED)', 'LIBS = -lws2_32 $(LIBRUBYARG_SHARED)'
67
70
  File.open('Makefile', 'w') { |f| f.write makefile_contents }
68
71
  end
@@ -13,6 +13,7 @@
13
13
  static VALUE mCoolio = Qnil;
14
14
  static VALUE cCoolio_Watcher = Qnil;
15
15
  static VALUE cCoolio_StatWatcher = Qnil;
16
+ static VALUE cCoolio_StatInfo = Qnil;
16
17
  static VALUE cCoolio_Loop = Qnil;
17
18
 
18
19
  static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self);
@@ -20,9 +21,11 @@ static VALUE Coolio_StatWatcher_attach(VALUE self, VALUE loop);
20
21
  static VALUE Coolio_StatWatcher_detach(VALUE self);
21
22
  static VALUE Coolio_StatWatcher_enable(VALUE self);
22
23
  static VALUE Coolio_StatWatcher_disable(VALUE self);
23
- static VALUE Coolio_StatWatcher_on_change(VALUE self);
24
+ static VALUE Coolio_StatWatcher_on_change(VALUE self, VALUE previous, VALUE current);
24
25
  static VALUE Coolio_StatWatcher_path(VALUE self);
25
26
 
27
+ static VALUE Coolio_StatInfo_build(ev_statdata *statdata_struct);
28
+
26
29
  static void Coolio_StatWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_stat *stat, int revents);
27
30
  static void Coolio_StatWatcher_dispatch_callback(VALUE self, int revents);
28
31
 
@@ -30,12 +33,27 @@ static void Coolio_StatWatcher_dispatch_callback(VALUE self, int revents);
30
33
  * Coolio::StatWatcher lets you create either one-shot or periodic stats which
31
34
  * run within Coolio's event loop. It's useful for creating timeouts or
32
35
  * events which fire periodically.
33
- */
36
+ **/
34
37
  void Init_coolio_stat_watcher()
35
- {
38
+ {
36
39
  mCoolio = rb_define_module("Coolio");
37
40
  cCoolio_Watcher = rb_define_class_under(mCoolio, "Watcher", rb_cObject);
38
41
  cCoolio_StatWatcher = rb_define_class_under(mCoolio, "StatWatcher", cCoolio_Watcher);
42
+ cCoolio_StatInfo = rb_struct_define("StatInfo",
43
+ "mtime",
44
+ "ctime",
45
+ "atime",
46
+ "dev",
47
+ "ino",
48
+ "mode",
49
+ "nlink",
50
+ "uid",
51
+ "guid",
52
+ "rdev",
53
+ "size",
54
+ "blksize",
55
+ "blocks",
56
+ NULL);
39
57
  cCoolio_Loop = rb_define_class_under(mCoolio, "Loop", rb_cObject);
40
58
 
41
59
  rb_define_method(cCoolio_StatWatcher, "initialize", Coolio_StatWatcher_initialize, -1);
@@ -43,14 +61,14 @@ void Init_coolio_stat_watcher()
43
61
  rb_define_method(cCoolio_StatWatcher, "detach", Coolio_StatWatcher_detach, 0);
44
62
  rb_define_method(cCoolio_StatWatcher, "enable", Coolio_StatWatcher_enable, 0);
45
63
  rb_define_method(cCoolio_StatWatcher, "disable", Coolio_StatWatcher_disable, 0);
46
- rb_define_method(cCoolio_StatWatcher, "on_change", Coolio_StatWatcher_on_change, 0);
64
+ rb_define_method(cCoolio_StatWatcher, "on_change", Coolio_StatWatcher_on_change, 2);
47
65
  rb_define_method(cCoolio_StatWatcher, "path", Coolio_StatWatcher_path, 0);
48
66
  }
49
67
 
50
68
  /**
51
69
  * call-seq:
52
70
  * Coolio::StatWatcher.initialize(path, interval = 0) -> Coolio::StatWatcher
53
- *
71
+ *
54
72
  * Create a new Coolio::StatWatcher for the given path. This will monitor the
55
73
  * given path for changes at the filesystem level. The interval argument
56
74
  * specified how often in seconds the path should be polled for changes.
@@ -75,11 +93,11 @@ static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
75
93
 
76
94
  watcher_data->dispatch_callback = Coolio_StatWatcher_dispatch_callback;
77
95
  ev_stat_init(
78
- &watcher_data->event_types.ev_stat,
79
- Coolio_StatWatcher_libev_callback,
80
- RSTRING_PTR(path),
96
+ &watcher_data->event_types.ev_stat,
97
+ Coolio_StatWatcher_libev_callback,
98
+ RSTRING_PTR(path),
81
99
  interval == Qnil ? 0 : NUM2DBL(interval)
82
- );
100
+ );
83
101
  watcher_data->event_types.ev_stat.data = (void *)self;
84
102
 
85
103
  return Qnil;
@@ -88,7 +106,7 @@ static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
88
106
  /**
89
107
  * call-seq:
90
108
  * Coolio::StatWatcher.attach(loop) -> Coolio::StatWatcher
91
- *
109
+ *
92
110
  * Attach the stat watcher to the given Coolio::Loop. If the watcher is already
93
111
  * attached to a loop, detach it from the old one and attach it to the new one.
94
112
  */
@@ -97,7 +115,7 @@ static VALUE Coolio_StatWatcher_attach(VALUE self, VALUE loop)
97
115
  ev_tstamp interval, timeout;
98
116
  struct Coolio_Loop *loop_data;
99
117
  struct Coolio_Watcher *watcher_data;
100
-
118
+
101
119
  if(!rb_obj_is_kind_of(loop, cCoolio_Loop))
102
120
  rb_raise(rb_eArgError, "expected loop to be an instance of Coolio::Loop");
103
121
 
@@ -112,13 +130,13 @@ static VALUE Coolio_StatWatcher_attach(VALUE self, VALUE loop)
112
130
  ev_stat_start(loop_data->ev_loop, &watcher_data->event_types.ev_stat);
113
131
  rb_call_super(1, &loop);
114
132
 
115
- return self;
133
+ return self;
116
134
  }
117
135
 
118
136
  /**
119
137
  * call-seq:
120
138
  * Coolio::StatWatcher.detach -> Coolio::StatWatcher
121
- *
139
+ *
122
140
  * Detach the stat watcher from its current Coolio::Loop.
123
141
  */
124
142
  static VALUE Coolio_StatWatcher_detach(VALUE self)
@@ -131,7 +149,7 @@ static VALUE Coolio_StatWatcher_detach(VALUE self)
131
149
  /**
132
150
  * call-seq:
133
151
  * Coolio::StatWatcher.enable -> Coolio::StatWatcher
134
- *
152
+ *
135
153
  * Re-enable a stat watcher which has been temporarily disabled. See the
136
154
  * disable method for a more thorough explanation.
137
155
  */
@@ -139,15 +157,15 @@ static VALUE Coolio_StatWatcher_enable(VALUE self)
139
157
  {
140
158
  Watcher_Enable(stat, self);
141
159
 
142
- return self;
160
+ return self;
143
161
  }
144
162
 
145
163
  /**
146
164
  * call-seq:
147
165
  * Coolio::StatWatcher.disable -> Coolio::StatWatcher
148
- *
149
- * Temporarily disable a stat watcher which is attached to a loop.
150
- * This is useful if you wish to toggle event monitoring on and off.
166
+ *
167
+ * Temporarily disable a stat watcher which is attached to a loop.
168
+ * This is useful if you wish to toggle event monitoring on and off.
151
169
  */
152
170
  static VALUE Coolio_StatWatcher_disable(VALUE self)
153
171
  {
@@ -159,10 +177,10 @@ static VALUE Coolio_StatWatcher_disable(VALUE self)
159
177
  /**
160
178
  * call-seq:
161
179
  * Coolio::StatWatcher#on_change -> nil
162
- *
180
+ *
163
181
  * Called whenever the status of the given path changes
164
182
  */
165
- static VALUE Coolio_StatWatcher_on_change(VALUE self)
183
+ static VALUE Coolio_StatWatcher_on_change(VALUE self, VALUE previous, VALUE current)
166
184
  {
167
185
  return Qnil;
168
186
  }
@@ -170,7 +188,7 @@ static VALUE Coolio_StatWatcher_on_change(VALUE self)
170
188
  /**
171
189
  * call-seq:
172
190
  * Coolio::StatWatcher#path -> String
173
- *
191
+ *
174
192
  * Retrieve the path associated with this StatWatcher
175
193
  */
176
194
  static VALUE Coolio_StatWatcher_path(VALUE self)
@@ -186,6 +204,64 @@ static void Coolio_StatWatcher_libev_callback(struct ev_loop *ev_loop, struct ev
186
204
 
187
205
  /* Coolio::Loop dispatch callback */
188
206
  static void Coolio_StatWatcher_dispatch_callback(VALUE self, int revents)
189
- {
190
- rb_funcall(self, rb_intern("on_change"), 0, 0);
207
+ {
208
+ struct Coolio_Watcher *watcher_data;
209
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
210
+
211
+ VALUE previous_statdata = Coolio_StatInfo_build(&watcher_data->event_types.ev_stat.prev);
212
+ VALUE current_statdata = Coolio_StatInfo_build(&watcher_data->event_types.ev_stat.attr);
213
+ rb_funcall(self, rb_intern("on_change"), 2, previous_statdata, current_statdata);
214
+ }
215
+
216
+ /**
217
+ * Convience method to build StatInfo structs given an ev_statdata
218
+ * */
219
+ static VALUE Coolio_StatInfo_build(ev_statdata *statdata_struct)
220
+ {
221
+ VALUE at_method = rb_intern("at");
222
+ VALUE cTime = rb_const_get(rb_cObject, rb_intern("Time"));
223
+
224
+ VALUE mtime = Qnil;
225
+ VALUE ctime = Qnil;
226
+ VALUE atime = Qnil;
227
+ VALUE dev = Qnil;
228
+ VALUE ino = Qnil;
229
+ VALUE mode = Qnil;
230
+ VALUE nlink = Qnil;
231
+ VALUE uid = Qnil;
232
+ VALUE gid = Qnil;
233
+ VALUE rdev = Qnil;
234
+ VALUE size = Qnil;
235
+ VALUE blksize = Qnil;
236
+ VALUE blocks = Qnil;
237
+
238
+ mtime = rb_funcall(cTime, at_method, 1, INT2NUM(statdata_struct->st_mtime));
239
+ ctime = rb_funcall(cTime, at_method, 1, INT2NUM(statdata_struct->st_ctime));
240
+ atime = rb_funcall(cTime, at_method, 1, INT2NUM(statdata_struct->st_atime));
241
+ dev = INT2NUM(statdata_struct->st_dev);
242
+ ino = INT2NUM(statdata_struct->st_ino);
243
+ mode = INT2NUM(statdata_struct->st_mode);
244
+ nlink = INT2NUM(statdata_struct->st_nlink);
245
+ uid = INT2NUM(statdata_struct->st_uid);
246
+ gid = INT2NUM(statdata_struct->st_gid);
247
+ rdev = INT2NUM(statdata_struct->st_rdev);
248
+ size = INT2NUM(statdata_struct->st_size);
249
+ blksize = INT2NUM(statdata_struct->st_blksize);
250
+ blocks = INT2NUM(statdata_struct->st_blocks);
251
+
252
+ return rb_struct_new(cCoolio_StatInfo,
253
+ mtime,
254
+ ctime,
255
+ atime,
256
+ dev,
257
+ ino,
258
+ mode,
259
+ nlink,
260
+ uid,
261
+ gid,
262
+ rdev,
263
+ size,
264
+ blksize,
265
+ blocks,
266
+ NULL);
191
267
  }
@@ -1,5 +1,29 @@
1
1
  Revision history for libev, a high-performance and full-featured event loop.
2
2
 
3
+ 4.04 Wed Feb 16 09:01:51 CET 2011
4
+ - fix two problems in the native win32 backend, where reuse of fd's
5
+ with different underlying handles caused handles not to be removed
6
+ or added to the select set (analyzed and tested by Bert Belder).
7
+ - do no rely on ceil() in ev_e?poll.c.
8
+ - backport libev to HP-UX versions before 11 v3.
9
+ - configure did not detect nanosleep and clock_gettime properly when
10
+ they are available in the libc (as opposed to -lrt).
11
+
12
+ 4.03 Tue Jan 11 14:37:25 CET 2011
13
+ - officially support polling files with all backends.
14
+ - support files, /dev/zero etc. the same way as select in the epoll
15
+ backend, by generating events on our own.
16
+ - ports backend: work around solaris bug 6874410 and many related ones
17
+ (EINTR, maybe more), with no performance loss (note that the solaris
18
+ bug report is actually wrong, reality is far more bizarre and broken
19
+ than that).
20
+ - define EV_READ/EV_WRITE as macros in event.h, as some programs use
21
+ #ifdef to test for them.
22
+ - new (experimental) function: ev_feed_signal.
23
+ - new (to become default) EVFLAG_NOSIGMASK flag.
24
+ - new EVBACKEND_MASK symbol.
25
+ - updated COMMON IDIOMS SECTION.
26
+
3
27
  4.01 Fri Nov 5 21:51:29 CET 2010
4
28
  - automake fucked it up, apparently, --add-missing -f is not quite enough
5
29
  to make it update its files, so 4.00 didn't install ev++.h and
@@ -1,19 +1,19 @@
1
1
  /*
2
2
  * libev event processing core, watcher management
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011 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-
8
8
  * tion, are permitted provided that the following conditions are met:
9
- *
9
+ *
10
10
  * 1. Redistributions of source code must retain the above copyright notice,
11
11
  * this list of conditions and the following disclaimer.
12
- *
12
+ *
13
13
  * 2. Redistributions in binary form must reproduce the above copyright
14
14
  * notice, this list of conditions and the following disclaimer in the
15
15
  * documentation and/or other materials provided with the distribution.
16
- *
16
+ *
17
17
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
18
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
19
  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
@@ -378,7 +378,8 @@ EV_CPP(extern "C" {)
378
378
  #endif
379
379
 
380
380
  #if !EV_USE_NANOSLEEP
381
- # ifndef _WIN32
381
+ /* hp-ux has it in sys/time.h, which we unconditionally include above */
382
+ # if !defined(_WIN32) && !defined(__hpux)
382
383
  # include <sys/select.h>
383
384
  # endif
384
385
  #endif
@@ -817,6 +818,14 @@ ev_sleep (ev_tstamp delay)
817
818
  }
818
819
  }
819
820
 
821
+ inline_speed int
822
+ ev_timeout_to_ms (ev_tstamp timeout)
823
+ {
824
+ int ms = timeout * 1000. + .999999;
825
+
826
+ return expect_true (ms) ? ms : timeout < 1e-6 ? 0 : 1;
827
+ }
828
+
820
829
  /*****************************************************************************/
821
830
 
822
831
  #define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */
@@ -967,6 +976,31 @@ fd_reify (EV_P)
967
976
  {
968
977
  int i;
969
978
 
979
+ #if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
980
+ for (i = 0; i < fdchangecnt; ++i)
981
+ {
982
+ int fd = fdchanges [i];
983
+ ANFD *anfd = anfds + fd;
984
+
985
+ if (anfd->reify & EV__IOFDSET)
986
+ {
987
+ SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);
988
+
989
+ if (handle != anfd->handle)
990
+ {
991
+ unsigned long arg;
992
+
993
+ assert (("libev: only socket fds supported in this configuration", ioctlsocket (handle, FIONREAD, &arg) == 0));
994
+
995
+ /* handle changed, but fd didn't - we need to do it in two steps */
996
+ backend_modify (EV_A_ fd, anfd->events, 0);
997
+ anfd->events = 0;
998
+ anfd->handle = handle;
999
+ }
1000
+ }
1001
+ }
1002
+ #endif
1003
+
970
1004
  for (i = 0; i < fdchangecnt; ++i)
971
1005
  {
972
1006
  int fd = fdchanges [i];
@@ -978,16 +1012,6 @@ fd_reify (EV_P)
978
1012
 
979
1013
  anfd->reify = 0;
980
1014
 
981
- #if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
982
- if (o_reify & EV__IOFDSET)
983
- {
984
- unsigned long arg;
985
- anfd->handle = EV_FD_TO_WIN32_HANDLE (fd);
986
- assert (("libev: only socket fds supported in this configuration", ioctlsocket (anfd->handle, FIONREAD, &arg) == 0));
987
- printf ("oi %d %x\n", fd, anfd->handle);//D
988
- }
989
- #endif
990
-
991
1015
  /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
992
1016
  {
993
1017
  anfd->events = 0;
@@ -1345,14 +1369,16 @@ pipecb (EV_P_ ev_io *iow, int revents)
1345
1369
  read (evpipe [0], &dummy, 1);
1346
1370
  }
1347
1371
 
1372
+ #if EV_SIGNAL_ENABLE
1348
1373
  if (sig_pending)
1349
- {
1374
+ {
1350
1375
  sig_pending = 0;
1351
1376
 
1352
1377
  for (i = EV_NSIG - 1; i--; )
1353
1378
  if (expect_false (signals [i].pending))
1354
1379
  ev_feed_signal_event (EV_A_ i + 1);
1355
1380
  }
1381
+ #endif
1356
1382
 
1357
1383
  #if EV_ASYNC_ENABLE
1358
1384
  if (async_pending)
@@ -1371,19 +1397,28 @@ pipecb (EV_P_ ev_io *iow, int revents)
1371
1397
 
1372
1398
  /*****************************************************************************/
1373
1399
 
1374
- static void
1375
- ev_sighandler (int signum)
1400
+ void
1401
+ ev_feed_signal (int signum)
1376
1402
  {
1377
1403
  #if EV_MULTIPLICITY
1378
1404
  EV_P = signals [signum - 1].loop;
1405
+
1406
+ if (!EV_A)
1407
+ return;
1379
1408
  #endif
1380
1409
 
1410
+ signals [signum - 1].pending = 1;
1411
+ evpipe_write (EV_A_ &sig_pending);
1412
+ }
1413
+
1414
+ static void
1415
+ ev_sighandler (int signum)
1416
+ {
1381
1417
  #ifdef _WIN32
1382
1418
  signal (signum, ev_sighandler);
1383
1419
  #endif
1384
1420
 
1385
- signals [signum - 1].pending = 1;
1386
- evpipe_write (EV_A_ &sig_pending);
1421
+ ev_feed_signal (signum);
1387
1422
  }
1388
1423
 
1389
1424
  void noinline
@@ -1645,6 +1680,8 @@ loop_init (EV_P_ unsigned int flags)
1645
1680
  {
1646
1681
  if (!backend)
1647
1682
  {
1683
+ origflags = flags;
1684
+
1648
1685
  #if EV_USE_REALTIME
1649
1686
  if (!have_realtime)
1650
1687
  {
@@ -1699,7 +1736,7 @@ loop_init (EV_P_ unsigned int flags)
1699
1736
  sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
1700
1737
  #endif
1701
1738
 
1702
- if (!(flags & 0x0000ffffU))
1739
+ if (!(flags & EVBACKEND_MASK))
1703
1740
  flags |= ev_recommended_backends ();
1704
1741
 
1705
1742
  #if EV_USE_IOCP
@@ -2102,9 +2139,6 @@ ev_invoke_pending (EV_P)
2102
2139
  {
2103
2140
  ANPENDING *p = pendings [pri] + --pendingcnt [pri];
2104
2141
 
2105
- /*assert (("libev: non-pending watcher on pending list", p->w->pending));*/
2106
- /* ^ this is no longer true, as pending_w could be here */
2107
-
2108
2142
  p->w->pending = 0;
2109
2143
  EV_CB_INVOKE (p->w, p->events);
2110
2144
  EV_FREQUENT_CHECK;
@@ -2175,6 +2209,15 @@ timers_reify (EV_P)
2175
2209
  }
2176
2210
 
2177
2211
  #if EV_PERIODIC_ENABLE
2212
+
2213
+ inline_speed void
2214
+ periodic_recalc (EV_P_ ev_periodic *w)
2215
+ {
2216
+ /* TODO: use slow but potentially more correct incremental algo, */
2217
+ /* also do not rely on ceil */
2218
+ ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
2219
+ }
2220
+
2178
2221
  /* make periodics pending */
2179
2222
  inline_size void
2180
2223
  periodics_reify (EV_P)
@@ -2203,7 +2246,8 @@ periodics_reify (EV_P)
2203
2246
  }
2204
2247
  else if (w->interval)
2205
2248
  {
2206
- ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
2249
+ periodic_recalc (EV_A_ w);
2250
+
2207
2251
  /* if next trigger time is not sufficiently in the future, put it there */
2208
2252
  /* this might happen because of floating point inexactness */
2209
2253
  if (ev_at (w) - ev_rt_now < TIME_EPSILON)
@@ -2247,7 +2291,7 @@ periodics_reschedule (EV_P)
2247
2291
  if (w->reschedule_cb)
2248
2292
  ev_at (w) = w->reschedule_cb (w, ev_rt_now);
2249
2293
  else if (w->interval)
2250
- ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
2294
+ periodic_recalc (EV_A_ w);
2251
2295
 
2252
2296
  ANHE_at_cache (periodics [i]);
2253
2297
  }
@@ -2749,8 +2793,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
2749
2793
  else if (w->interval)
2750
2794
  {
2751
2795
  assert (("libev: ev_periodic_start called with negative interval value", w->interval >= 0.));
2752
- /* this formula differs from the one in periodic_reify because we do not always round up */
2753
- ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
2796
+ periodic_recalc (EV_A_ w);
2754
2797
  }
2755
2798
  else
2756
2799
  ev_at (w) = w->offset;
@@ -2881,9 +2924,12 @@ ev_signal_start (EV_P_ ev_signal *w)
2881
2924
  sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
2882
2925
  sigaction (w->signum, &sa, 0);
2883
2926
 
2884
- sigemptyset (&sa.sa_mask);
2885
- sigaddset (&sa.sa_mask, w->signum);
2886
- sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);
2927
+ if (origflags & EVFLAG_NOSIGMASK)
2928
+ {
2929
+ sigemptyset (&sa.sa_mask);
2930
+ sigaddset (&sa.sa_mask, w->signum);
2931
+ sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);
2932
+ }
2887
2933
  #endif
2888
2934
  }
2889
2935
 
@@ -3034,7 +3080,7 @@ infy_add (EV_P_ ev_stat *w)
3034
3080
 
3035
3081
  *pend = 0;
3036
3082
  w->wd = inotify_add_watch (fs_fd, path, mask);
3037
- }
3083
+ }
3038
3084
  while (w->wd < 0 && (errno == ENOENT || errno == EACCES));
3039
3085
  }
3040
3086
  }