cool.io 1.4.1-x64-mingw32

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +29 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGES.md +229 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +20 -0
  8. data/README.md +166 -0
  9. data/Rakefile +79 -0
  10. data/cool.io.gemspec +29 -0
  11. data/examples/callbacked_echo_server.rb +24 -0
  12. data/examples/dslified_echo_client.rb +34 -0
  13. data/examples/dslified_echo_server.rb +24 -0
  14. data/examples/echo_client.rb +38 -0
  15. data/examples/echo_server.rb +27 -0
  16. data/examples/google.rb +9 -0
  17. data/ext/cool.io/.gitignore +5 -0
  18. data/ext/cool.io/cool.io.h +59 -0
  19. data/ext/cool.io/cool.io_ext.c +25 -0
  20. data/ext/cool.io/ev_wrap.h +10 -0
  21. data/ext/cool.io/extconf.rb +61 -0
  22. data/ext/cool.io/iowatcher.c +189 -0
  23. data/ext/cool.io/libev.c +8 -0
  24. data/ext/cool.io/loop.c +261 -0
  25. data/ext/cool.io/stat_watcher.c +269 -0
  26. data/ext/cool.io/timer_watcher.c +219 -0
  27. data/ext/cool.io/utils.c +122 -0
  28. data/ext/cool.io/watcher.c +264 -0
  29. data/ext/cool.io/watcher.h +71 -0
  30. data/ext/iobuffer/extconf.rb +9 -0
  31. data/ext/iobuffer/iobuffer.c +767 -0
  32. data/ext/libev/Changes +507 -0
  33. data/ext/libev/LICENSE +37 -0
  34. data/ext/libev/README +58 -0
  35. data/ext/libev/README.embed +3 -0
  36. data/ext/libev/ev.c +5054 -0
  37. data/ext/libev/ev.h +853 -0
  38. data/ext/libev/ev_epoll.c +282 -0
  39. data/ext/libev/ev_kqueue.c +214 -0
  40. data/ext/libev/ev_poll.c +148 -0
  41. data/ext/libev/ev_port.c +185 -0
  42. data/ext/libev/ev_select.c +362 -0
  43. data/ext/libev/ev_vars.h +204 -0
  44. data/ext/libev/ev_win32.c +163 -0
  45. data/ext/libev/ev_wrap.h +200 -0
  46. data/ext/libev/ruby_gil.patch +97 -0
  47. data/ext/libev/test_libev_win32.c +123 -0
  48. data/ext/libev/win_select.patch +115 -0
  49. data/lib/.gitignore +2 -0
  50. data/lib/cool.io.rb +34 -0
  51. data/lib/cool.io/async_watcher.rb +43 -0
  52. data/lib/cool.io/custom_require.rb +9 -0
  53. data/lib/cool.io/dns_resolver.rb +219 -0
  54. data/lib/cool.io/dsl.rb +139 -0
  55. data/lib/cool.io/io.rb +194 -0
  56. data/lib/cool.io/iowatcher.rb +17 -0
  57. data/lib/cool.io/listener.rb +99 -0
  58. data/lib/cool.io/loop.rb +122 -0
  59. data/lib/cool.io/meta.rb +49 -0
  60. data/lib/cool.io/server.rb +75 -0
  61. data/lib/cool.io/socket.rb +230 -0
  62. data/lib/cool.io/timer_watcher.rb +17 -0
  63. data/lib/cool.io/version.rb +7 -0
  64. data/lib/coolio.rb +2 -0
  65. data/spec/async_watcher_spec.rb +57 -0
  66. data/spec/dns_spec.rb +43 -0
  67. data/spec/iobuffer_spec.rb +147 -0
  68. data/spec/spec_helper.rb +19 -0
  69. data/spec/stat_watcher_spec.rb +77 -0
  70. data/spec/tcp_server_spec.rb +225 -0
  71. data/spec/tcp_socket_spec.rb +185 -0
  72. data/spec/timer_watcher_spec.rb +59 -0
  73. data/spec/udp_socket_spec.rb +58 -0
  74. data/spec/unix_listener_spec.rb +25 -0
  75. data/spec/unix_server_spec.rb +27 -0
  76. metadata +182 -0
@@ -0,0 +1,79 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/clean'
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+
7
+ RSpec::Core::RakeTask.new(:rcov) do |task|
8
+ task.rcov = true
9
+ end
10
+
11
+ task :default => %w(compile spec)
12
+
13
+ require 'rdoc/task'
14
+ Rake::RDocTask.new do |rdoc|
15
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
16
+
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = "cool.io #{version}"
19
+ rdoc.rdoc_files.include('README*')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ require 'rake/extensiontask'
24
+
25
+ spec = eval(File.read("cool.io.gemspec"))
26
+
27
+ def configure_cross_compilation(ext)
28
+ unless RUBY_PLATFORM =~ /mswin|mingw/
29
+ ext.cross_compile = true
30
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
31
+ end
32
+ end
33
+
34
+ Rake::ExtensionTask.new('iobuffer_ext', spec) do |ext|
35
+ ext.ext_dir = 'ext/iobuffer'
36
+ configure_cross_compilation(ext)
37
+ end
38
+
39
+ Rake::ExtensionTask.new('cool.io_ext', spec) do |ext|
40
+ ext.ext_dir = 'ext/cool.io'
41
+ configure_cross_compilation(ext)
42
+ end
43
+
44
+ # Note that this rake-compiler-dock rake task dose not support bundle install(1) --path option.
45
+ # Please use bundle install instead when you execute this rake task.
46
+ namespace :build do
47
+ desc 'Build gems for Windows per rake-compiler-dock'
48
+ task :windows do
49
+ require 'rake_compiler_dock'
50
+ RakeCompilerDock.sh <<-CROSS
51
+ bundle
52
+ rake cross native gem RUBY_CC_VERSION='2.0.0:2.1.6:2.2.2'
53
+ CROSS
54
+ end
55
+ end
56
+
57
+ # adapted from http://flavoriffic.blogspot.com/2009/06/easily-valgrind-gdb-your-ruby-c.html
58
+ def specs_command
59
+ require "find"
60
+ files = []
61
+ Find.find("spec") do |f|
62
+ files << f if File.basename(f) =~ /.*spec.*\.rb$/
63
+ end
64
+ cmdline = "#{RUBY} -I.:lib:ext:spec \
65
+ -e '%w[#{files.join(' ')}].each { |f| require f }'"
66
+ end
67
+
68
+ namespace :spec do
69
+ desc "run specs with valgrind"
70
+ task :valgrind => :compile do
71
+ system "valgrind --num-callers=15 \
72
+ --partial-loads-ok=yes --undef-value-errors=no \
73
+ --tool=memcheck --leak-check=yes --track-fds=yes \
74
+ --show-reachable=yes #{specs_command}"
75
+ end
76
+ end
77
+
78
+ CLEAN.include "**/*.rbc", "**/*.o", "**/*.so", "**/*.bundle"
79
+ CLEAN.exclude "vendor/**/*.rbc", "vendor/**/*.o", "vendor/**/*.so", "vendor/**/*.bundle"
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cool.io/version"
4
+
5
+ module Cool
6
+ # Allow Coolio module to be referenced as Cool.io
7
+ def self.io; Coolio; end
8
+ end
9
+
10
+ Gem::Specification.new do |s|
11
+ s.name = "cool.io"
12
+ s.version = Coolio::VERSION
13
+ s.authors = ["Tony Arcieri", "Masahiro Nakagawa"]
14
+ s.email = ["tony.arcieri@gmail.com", "repeatedly@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"
18
+ s.extensions = ["ext/cool.io/extconf.rb", "ext/iobuffer/extconf.rb"]
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_development_dependency "rake-compiler", "~> 0.9.5"
26
+ s.add_development_dependency "rake-compiler-dock", "~> 0.4.3"
27
+ s.add_development_dependency "rspec", ">= 2.13.0"
28
+ s.add_development_dependency "rdoc", ">= 3.6.0"
29
+ end
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ event_loop = Cool.io::Loop.default
10
+ server = Cool.io::TCPServer.new(ADDR, PORT) do |connection|
11
+ puts "#{connection.remote_addr}:#{connection.remote_port} connected"
12
+
13
+ connection.on_close do
14
+ puts "#{connection.remote_addr}:#{connection.remote_port} disconnected"
15
+ end
16
+
17
+ connection.on_read do |data|
18
+ connection.write data
19
+ end
20
+ end
21
+ server.attach(event_loop)
22
+
23
+ puts "Echo server listening on #{ADDR}:#{PORT}"
24
+ event_loop.run
@@ -0,0 +1,34 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ cool.io.connect ADDR, PORT do
10
+ on_connect do
11
+ puts "Connected to #{remote_host}:#{remote_port}"
12
+ write "bounce this back to me"
13
+ end
14
+
15
+ on_close do
16
+ puts "Disconnected from #{remote_host}:#{remote_port}"
17
+ end
18
+
19
+ on_read do |data|
20
+ puts "Got: #{data}"
21
+ close
22
+ end
23
+
24
+ on_resolve_failed do
25
+ puts "Error: Couldn't resolve #{remote_host}"
26
+ end
27
+
28
+ on_connect_failed do
29
+ puts "Error: Connection refused to #{remote_host}:#{remote_port}"
30
+ end
31
+ end
32
+
33
+ puts "Echo client connecting to #{ADDR}:#{PORT}..."
34
+ cool.io.run
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ cool.io.server ADDR, PORT do
10
+ on_connect do
11
+ puts "#{remote_addr}:#{remote_port} connected"
12
+ end
13
+
14
+ on_close do
15
+ puts "#{remote_addr}:#{remote_port} disconnected"
16
+ end
17
+
18
+ on_read do |data|
19
+ write data
20
+ end
21
+ end
22
+
23
+ puts "Echo server listening on #{ADDR}:#{PORT}"
24
+ cool.io.run
@@ -0,0 +1,38 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ class ClientConnection < Cool.io::TCPSocket
10
+ def on_connect
11
+ puts "#{remote_addr}:#{remote_port} connected"
12
+ write "bounce this back to me"
13
+ end
14
+
15
+ def on_close
16
+ puts "#{remote_addr}:#{remote_port} disconnected"
17
+ end
18
+
19
+ def on_read(data)
20
+ print "got #{data}"
21
+ close
22
+ end
23
+
24
+ def on_resolve_failed
25
+ print "DNS resolve failed"
26
+ end
27
+
28
+ def on_connect_failed
29
+ print "connect failed, meaning our connection to their port was rejected"
30
+ end
31
+
32
+ end
33
+
34
+ event_loop = Cool.io::Loop.default
35
+ client = ClientConnection.connect(ADDR, PORT)
36
+ client.attach(event_loop)
37
+ puts "Echo client connecting to #{ADDR}:#{PORT}..."
38
+ event_loop.run
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ ADDR = '127.0.0.1'
7
+ PORT = 4321
8
+
9
+ class EchoServerConnection < Cool.io::TCPSocket
10
+ def on_connect
11
+ puts "#{remote_addr}:#{remote_port} connected"
12
+ end
13
+
14
+ def on_close
15
+ puts "#{remote_addr}:#{remote_port} disconnected"
16
+ end
17
+
18
+ def on_read(data)
19
+ write data
20
+ end
21
+ end
22
+
23
+ event_loop = Cool.io::Loop.default
24
+ Cool.io::TCPServer.new(ADDR, PORT, EchoServerConnection).attach(event_loop)
25
+
26
+ puts "Echo server listening on #{ADDR}:#{PORT}"
27
+ event_loop.run
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'cool.io'
5
+
6
+ l = Coolio::Loop.default
7
+ c = Coolio::HttpClient.connect("www.google.com", 80).attach(l)
8
+ c.request('GET', '/search', :query => { :q => 'feces'})
9
+ l.run
@@ -0,0 +1,5 @@
1
+ Makefile
2
+ mkmf.log
3
+ *.o
4
+ *.so
5
+ *.bundle
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Copyright (C) 2007-10 Tony Arcieri
3
+ * You may redistribute this under the terms of the Ruby license.
4
+ * See LICENSE for details
5
+ */
6
+
7
+ #ifndef COOLIO_H
8
+ #define COOLIO_H
9
+
10
+ #include "ruby.h"
11
+ #include "rubyio.h"
12
+
13
+ #ifdef GetReadFile
14
+ #define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
15
+ #else
16
+
17
+ #if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
18
+ #define FPTR_TO_FD(fptr) fileno(fptr->f)
19
+ #else
20
+ #define FPTR_TO_FD(fptr) fptr->fd
21
+ #endif
22
+
23
+ #endif
24
+
25
+ struct Coolio_Event
26
+ {
27
+ /* These values are used to extract events from libev callbacks */
28
+ VALUE watcher;
29
+ int revents;
30
+ };
31
+
32
+ struct Coolio_Loop
33
+ {
34
+ struct ev_loop *ev_loop;
35
+ struct ev_timer timer; /* for timeouts */
36
+
37
+ int running;
38
+ int events_received;
39
+ int eventbuf_size;
40
+ struct Coolio_Event *eventbuf;
41
+ };
42
+
43
+ struct Coolio_Watcher
44
+ {
45
+ union {
46
+ struct ev_io ev_io;
47
+ struct ev_timer ev_timer;
48
+ struct ev_stat ev_stat;
49
+ } event_types;
50
+
51
+ int enabled;
52
+ VALUE loop;
53
+
54
+ void (*dispatch_callback)(VALUE self, int revents);
55
+ };
56
+
57
+ void Coolio_Loop_process_event(VALUE watcher, int revents);
58
+
59
+ #endif
@@ -0,0 +1,25 @@
1
+ /*
2
+ * Copyright (C) 2007-10 Tony Arcieri
3
+ * You may redistribute this under the terms of the Ruby license.
4
+ * See LICENSE for details
5
+ */
6
+
7
+
8
+ #include "ruby.h"
9
+
10
+ #include "ev_wrap.h"
11
+ #include "cool.io.h"
12
+
13
+ static VALUE mCoolio = Qnil;
14
+
15
+ /* Initialize the coolness */
16
+ void Init_cool()
17
+ {
18
+ /* Initializers for other modules */
19
+ Init_coolio_loop();
20
+ Init_coolio_watcher();
21
+ Init_coolio_iowatcher();
22
+ Init_coolio_timer_watcher();
23
+ Init_coolio_stat_watcher();
24
+ Init_coolio_utils();
25
+ }
@@ -0,0 +1,10 @@
1
+ #define EV_STANDALONE /* keeps ev from requiring config.h */
2
+
3
+ #ifdef _WIN32
4
+ #define EV_SELECT_IS_WINSOCKET 1 /* configure libev for windows select */
5
+ #define EV_USE_MONOTONIC 0
6
+ #define EV_USE_REALTIME 0
7
+ #endif
8
+
9
+ #include "../libev/ev.h"
10
+
@@ -0,0 +1,61 @@
1
+ require 'mkmf'
2
+
3
+ libs = []
4
+
5
+ $defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
6
+
7
+ have_func('rb_thread_blocking_region')
8
+ have_func('rb_thread_call_without_gvl')
9
+ have_func('rb_thread_alone')
10
+ have_func('rb_str_set_len')
11
+ have_library('rt', 'clock_gettime')
12
+
13
+ if have_header('sys/select.h')
14
+ $defs << '-DEV_USE_SELECT'
15
+ end
16
+
17
+ if have_header('poll.h')
18
+ $defs << '-DEV_USE_POLL'
19
+ end
20
+
21
+ if have_header('sys/epoll.h')
22
+ $defs << '-DEV_USE_EPOLL'
23
+ end
24
+
25
+ if have_header('sys/event.h') and have_header('sys/queue.h')
26
+ $defs << '-DEV_USE_KQUEUE'
27
+ end
28
+
29
+ if have_header('port.h')
30
+ $defs << '-DEV_USE_PORT'
31
+ end
32
+
33
+ have_header('sys/resource.h')
34
+
35
+ # ncpu detection specifics
36
+ case RUBY_PLATFORM
37
+ when /linux/
38
+ $defs << '-DHAVE_LINUX_PROCFS'
39
+ else
40
+ if have_func('sysctlbyname', ['sys/param.h', 'sys/sysctl.h'])
41
+ $defs << '-DHAVE_SYSCTLBYNAME'
42
+ end
43
+ end
44
+
45
+ $LIBS << ' ' << libs.join(' ')
46
+
47
+ dir_config('cool.io_ext')
48
+ create_makefile('cool.io_ext')
49
+
50
+ # win32 needs to link in "just the right order" for some reason or ioctlsocket will be mapped to an [inverted] ruby specific version. See libev mailing list for (not so helpful discussion--true cause I'm not sure, but this overcomes the symptom)
51
+ if RUBY_PLATFORM =~ /mingw|mswin/
52
+ makefile_contents = File.read 'Makefile'
53
+
54
+ # "Init_cool could not be found" when loading cool.io.so.
55
+ # I'm not sure why this is needed. But this line causes "1114 A dynamic link library (DLL) initialization routine failed." So I commented out this line.
56
+ #makefile_contents.gsub! 'DLDFLAGS = ', 'DLDFLAGS = -export-all '
57
+
58
+ makefile_contents.gsub! /LIBS = (.*) (\S*ws2_32\S*)/i, 'LIBS = \\2 \\1'
59
+ File.open('Makefile', 'w') { |f| f.write makefile_contents }
60
+ end
61
+
@@ -0,0 +1,189 @@
1
+ /*
2
+ * Copyright (C) 2007-10 Tony Arcieri
3
+ * You may redistribute this under the terms of the Ruby license.
4
+ * See LICENSE for details
5
+ */
6
+
7
+ #include "ruby.h"
8
+ #include "rubyio.h"
9
+
10
+ #include "ev_wrap.h"
11
+
12
+ #include "cool.io.h"
13
+ #include "watcher.h"
14
+
15
+ static VALUE mCoolio = Qnil;
16
+ static VALUE cCoolio_Watcher = Qnil;
17
+ static VALUE cCoolio_Loop = Qnil;
18
+ static VALUE cCoolio_IOWatcher = Qnil;
19
+
20
+ static VALUE Coolio_IOWatcher_initialize(int argc, VALUE *argv, VALUE self);
21
+ static VALUE Coolio_IOWatcher_attach(VALUE self, VALUE loop);
22
+ static VALUE Coolio_IOWatcher_detach(VALUE self);
23
+ static VALUE Coolio_IOWatcher_enable(VALUE self);
24
+ static VALUE Coolio_IOWatcher_disable(VALUE self);
25
+ static VALUE Coolio_IOWatcher_on_readable(VALUE self);
26
+ static VALUE Coolio_IOWatcher_on_writable(VALUE self);
27
+
28
+ static void Coolio_IOWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents);
29
+ static void Coolio_IOWatcher_dispatch_callback(VALUE self, int revents);
30
+
31
+ /*
32
+ * Coolio::IOWatcher monitors Ruby IO objects for readability or writability.
33
+ * This allows your application to block while the kernel is writing out
34
+ * data and fill the read or write buffer whenever there is space available.
35
+ */
36
+ void Init_coolio_iowatcher()
37
+ {
38
+ mCoolio = rb_define_module("Coolio");
39
+ cCoolio_Watcher = rb_define_class_under(mCoolio, "Watcher", rb_cObject);
40
+ cCoolio_IOWatcher = rb_define_class_under(mCoolio, "IOWatcher", cCoolio_Watcher);
41
+ cCoolio_Loop = rb_define_class_under(mCoolio, "Loop", rb_cObject);
42
+
43
+ rb_define_method(cCoolio_IOWatcher, "initialize", Coolio_IOWatcher_initialize, -1);
44
+ rb_define_method(cCoolio_IOWatcher, "attach", Coolio_IOWatcher_attach, 1);
45
+ rb_define_method(cCoolio_IOWatcher, "detach", Coolio_IOWatcher_detach, 0);
46
+ rb_define_method(cCoolio_IOWatcher, "enable", Coolio_IOWatcher_enable, 0);
47
+ rb_define_method(cCoolio_IOWatcher, "disable", Coolio_IOWatcher_disable, 0);
48
+ rb_define_method(cCoolio_IOWatcher, "on_readable", Coolio_IOWatcher_on_readable, 0);
49
+ rb_define_method(cCoolio_IOWatcher, "on_writable", Coolio_IOWatcher_on_writable, 0);
50
+ }
51
+
52
+ /**
53
+ * call-seq:
54
+ * Coolio::IOWatcher.initialize(IO, events = 'r') -> Coolio::IOWatcher
55
+ *
56
+ * Create a new Coolio::IOWatcher for the given IO object and add it to the given Coolio::Loop
57
+ */
58
+ static VALUE Coolio_IOWatcher_initialize(int argc, VALUE *argv, VALUE self)
59
+ {
60
+ VALUE io, flags;
61
+ char *flags_str;
62
+ int events;
63
+ struct Coolio_Watcher *watcher_data;
64
+ #if HAVE_RB_IO_T
65
+ rb_io_t *fptr;
66
+ #else
67
+ OpenFile *fptr;
68
+ #endif
69
+
70
+ rb_scan_args(argc, argv, "11", &io, &flags);
71
+
72
+ if(flags != Qnil)
73
+ flags_str = RSTRING_PTR(rb_String(flags));
74
+ else
75
+ flags_str = "r";
76
+
77
+ if(!strcmp(flags_str, "r"))
78
+ events = EV_READ;
79
+ else if(!strcmp(flags_str, "w"))
80
+ events = EV_WRITE;
81
+ else if(!strcmp(flags_str, "rw"))
82
+ events = EV_READ | EV_WRITE;
83
+ else
84
+ rb_raise(rb_eArgError, "invalid event type: '%s' (must be 'r', 'w', or 'rw')", flags_str);
85
+
86
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
87
+ GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
88
+
89
+ watcher_data->dispatch_callback = Coolio_IOWatcher_dispatch_callback;
90
+ ev_io_init(&watcher_data->event_types.ev_io, Coolio_IOWatcher_libev_callback, FPTR_TO_FD(fptr), events);
91
+ watcher_data->event_types.ev_io.data = (void *)self;
92
+
93
+ return Qnil;
94
+ }
95
+
96
+ /**
97
+ * call-seq:
98
+ * Coolio::IOWatcher.attach(loop) -> Coolio::IOWatcher
99
+ *
100
+ * Attach the IO watcher to the given Coolio::Loop. If the watcher is already attached
101
+ * to a loop, detach it from the old one and attach it to the new one.
102
+ */
103
+ static VALUE Coolio_IOWatcher_attach(VALUE self, VALUE loop)
104
+ {
105
+ Watcher_Attach(io, Coolio_IOWatcher_detach, self, loop);
106
+
107
+ return self;
108
+ }
109
+
110
+ /**
111
+ * call-seq:
112
+ * Coolio::IOWatcher.detach -> Coolio::IOWatcher
113
+ *
114
+ * Detach the IO watcher from its current Coolio::Loop.
115
+ */
116
+ static VALUE Coolio_IOWatcher_detach(VALUE self)
117
+ {
118
+ Watcher_Detach(io, self);
119
+
120
+ return self;
121
+ }
122
+
123
+ /**
124
+ * call-seq:
125
+ * Coolio::IOWatcher.enable -> Coolio::IOWatcher
126
+ *
127
+ * Re-enable an IO watcher which has been temporarily disabled. See the
128
+ * disable method for a more thorough explanation.
129
+ */
130
+ static VALUE Coolio_IOWatcher_enable(VALUE self)
131
+ {
132
+ Watcher_Enable(io, self);
133
+
134
+ return self;
135
+ }
136
+
137
+ /**
138
+ * call-seq:
139
+ * Coolio::IOWatcher.disable -> Coolio::IOWatcher
140
+ *
141
+ * Temporarily disable an IO watcher which is attached to a loop.
142
+ * This is useful if you wish to toggle event monitoring on and off.
143
+ */
144
+ static VALUE Coolio_IOWatcher_disable(VALUE self)
145
+ {
146
+ Watcher_Disable(io, self);
147
+
148
+ return self;
149
+ }
150
+
151
+ /**
152
+ * call-seq:
153
+ * Coolio::IOWatcher#on_readable -> nil
154
+ *
155
+ * Called whenever the IO object associated with the IOWatcher is readable
156
+ */
157
+ static VALUE Coolio_IOWatcher_on_readable(VALUE self)
158
+ {
159
+ return Qnil;
160
+ }
161
+
162
+ /**
163
+ * call-seq:
164
+ * Coolio::IOWatcher#on_writable -> nil
165
+ *
166
+ * Called whenever the IO object associated with the IOWatcher is writable
167
+ */
168
+
169
+ static VALUE Coolio_IOWatcher_on_writable(VALUE self)
170
+ {
171
+ return Qnil;
172
+ }
173
+
174
+ /* libev callback */
175
+ static void Coolio_IOWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents)
176
+ {
177
+ Coolio_Loop_process_event((VALUE)io->data, revents);
178
+ }
179
+
180
+ /* Coolio::Loop dispatch callback */
181
+ static void Coolio_IOWatcher_dispatch_callback(VALUE self, int revents)
182
+ {
183
+ if(revents & EV_READ)
184
+ rb_funcall(self, rb_intern("on_readable"), 0, 0);
185
+ else if(revents & EV_WRITE)
186
+ rb_funcall(self, rb_intern("on_writable"), 0, 0);
187
+ else
188
+ rb_raise(rb_eRuntimeError, "unknown revents value for ev_io: %d", revents);
189
+ }