cool.io 1.4.1-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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
+ }