cool.io 1.0.0 → 1.1.0

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.
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
  }