rev 0.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.
- data/LICENSE +58 -0
- data/README +107 -0
- data/ext/libev/ev.c +2440 -0
- data/ext/libev/ev.h +551 -0
- data/ext/libev/ev_epoll.c +174 -0
- data/ext/libev/ev_kqueue.c +186 -0
- data/ext/libev/ev_poll.c +127 -0
- data/ext/libev/ev_port.c +155 -0
- data/ext/libev/ev_select.c +236 -0
- data/ext/libev/ev_vars.h +108 -0
- data/ext/libev/ev_win32.c +117 -0
- data/ext/libev/ev_wrap.h +132 -0
- data/ext/rev/extconf.rb +36 -0
- data/ext/rev/rev.h +44 -0
- data/ext/rev/rev_ext.c +29 -0
- data/ext/rev/rev_io_watcher.c +157 -0
- data/ext/rev/rev_loop.c +254 -0
- data/ext/rev/rev_timer_watcher.c +153 -0
- data/ext/rev/rev_watcher.c +222 -0
- data/ext/rev/rev_watcher.h +79 -0
- data/lib/rev.rb +21 -0
- data/lib/rev/buffered_io.rb +123 -0
- data/lib/rev/dns_resolver.rb +178 -0
- data/lib/rev/io_watcher.rb +18 -0
- data/lib/rev/listener.rb +50 -0
- data/lib/rev/loop.rb +101 -0
- data/lib/rev/server.rb +53 -0
- data/lib/rev/socket.rb +186 -0
- data/lib/rev/timer_watcher.rb +18 -0
- data/lib/rev/watcher.rb +49 -0
- data/spec/rev_spec.rb +26 -0
- metadata +93 -0
data/lib/rev/loop.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C)2007 Tony Arcieri
|
3
|
+
# You can redistribute this under the terms of the Ruby license
|
4
|
+
# See file LICENSE for details
|
5
|
+
#++
|
6
|
+
|
7
|
+
require File.dirname(__FILE__) + '/../rev'
|
8
|
+
|
9
|
+
module Rev
|
10
|
+
class Loop
|
11
|
+
attr_reader :watchers
|
12
|
+
|
13
|
+
# Create a new Rev::Loop
|
14
|
+
#
|
15
|
+
# Options:
|
16
|
+
#
|
17
|
+
# :skip_environment (boolean)
|
18
|
+
# Ignore the $LIBEV_FLAGS environment variable
|
19
|
+
#
|
20
|
+
# :fork_check (boolean)
|
21
|
+
# Enable autodetection of forks
|
22
|
+
#
|
23
|
+
# :backend
|
24
|
+
# Choose the default backend, one (or many in an array) of:
|
25
|
+
# :select (most platforms)
|
26
|
+
# :poll (most platforms except Windows)
|
27
|
+
# :epoll (Linux)
|
28
|
+
# :kqueue (BSD/Mac OS X)
|
29
|
+
# :port (Solaris 10)
|
30
|
+
#
|
31
|
+
def initialize(options = {})
|
32
|
+
@watchers = []
|
33
|
+
@active_watchers = 0
|
34
|
+
|
35
|
+
flags = 0
|
36
|
+
|
37
|
+
options.each do |option, value|
|
38
|
+
case option
|
39
|
+
when :skip_environment
|
40
|
+
flags |= EVFLAG_NOEV if value
|
41
|
+
when :fork_check
|
42
|
+
flags |= EVFLAG_FORKCHECK if value
|
43
|
+
when :backend
|
44
|
+
value = [value] unless value.is_a? Array
|
45
|
+
value.each do |backend|
|
46
|
+
case backend
|
47
|
+
when :select then flags |= EVBACKEND_SELECT
|
48
|
+
when :poll then flags |= EVBACKEND_POLL
|
49
|
+
when :epoll then flags |= EVBACKEND_EPOLL
|
50
|
+
when :kqueue then flags |= EVBACKEND_KQUEUE
|
51
|
+
when :port then flags |= EVBACKEND_PORT
|
52
|
+
else raise ArgumentError, "no such backend: #{backend}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
else raise ArgumentError, "no such option: #{option}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
@loop = ev_loop_new(flags)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Attach a watcher to the loop
|
63
|
+
def attach(watcher)
|
64
|
+
watcher.attach self
|
65
|
+
end
|
66
|
+
|
67
|
+
# Run the event loop and dispatch events back to Ruby. If there
|
68
|
+
# are no watchers associated with the event loop it will return
|
69
|
+
# immediately. Otherwise, run will continue blocking and making
|
70
|
+
# event callbacks to watchers until all watchers associated with
|
71
|
+
# the loop have been disabled or detached. The loop may be
|
72
|
+
# explicitly stopped by calling the stop method on the loop object.
|
73
|
+
def run
|
74
|
+
raise RuntimeError, "no watchers for this loop" if @watchers.empty?
|
75
|
+
|
76
|
+
@running = true
|
77
|
+
while @running and not @active_watchers.zero?
|
78
|
+
run_once
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Stop the event loop if it's running
|
83
|
+
def stop
|
84
|
+
raise RuntimeError, "loop not running" unless @running
|
85
|
+
@running = false
|
86
|
+
end
|
87
|
+
|
88
|
+
#######
|
89
|
+
private
|
90
|
+
#######
|
91
|
+
|
92
|
+
EVFLAG_NOENV = 0x1000000 # do NOT consult environment
|
93
|
+
EVFLAG_FORKCHECK = 0x2000000 # check for a fork in each iteration
|
94
|
+
|
95
|
+
EVBACKEND_SELECT = 0x00000001 # supported about anywhere
|
96
|
+
EVBACKEND_POLL = 0x00000002 # !win
|
97
|
+
EVBACKEND_EPOLL = 0x00000004 # linux
|
98
|
+
EVBACKEND_KQUEUE = 0x00000008 # bsd
|
99
|
+
EVBACKEND_PORT = 0x00000020 # solaris 10
|
100
|
+
end
|
101
|
+
end
|
data/lib/rev/server.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C)2007 Tony Arcieri
|
3
|
+
# You can redistribute this under the terms of the Ruby license
|
4
|
+
# See file LICENSE for details
|
5
|
+
#++
|
6
|
+
|
7
|
+
require File.dirname(__FILE__) + '/../rev'
|
8
|
+
|
9
|
+
module Rev
|
10
|
+
class Server < Listener
|
11
|
+
def initialize(listen_socket, klass = Socket, *args, &block)
|
12
|
+
# Ensure the provided class responds to attach
|
13
|
+
unless (klass.instance_method(:attach) rescue nil)
|
14
|
+
raise ArgumentError, "provided class must respond to 'attach'"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Verify the arity of the provided arguments
|
18
|
+
arity = klass.instance_method(:initialize).arity
|
19
|
+
expected = arity >= 0 ? arity : -(arity + 1)
|
20
|
+
|
21
|
+
if (arity >= 0 and args.size + 1 != expected) or (arity < 0 and args.size + 1 < expected)
|
22
|
+
raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size+1} for #{expected})"
|
23
|
+
end
|
24
|
+
|
25
|
+
@klass, @args, @block = klass, args, block
|
26
|
+
super(listen_socket)
|
27
|
+
end
|
28
|
+
|
29
|
+
#########
|
30
|
+
protected
|
31
|
+
#########
|
32
|
+
|
33
|
+
def on_connection(socket)
|
34
|
+
connection = @klass.new(socket, *@args).attach(evloop)
|
35
|
+
@block.(connection) if @block
|
36
|
+
connection.on_connect
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class TCPServer < Server
|
41
|
+
def initialize(host, port, klass = TCPSocket, *args, &block)
|
42
|
+
listen_socket = ::TCPServer.new(host, port)
|
43
|
+
listen_socket.instance_eval { listen(1024) } # Change listen backlog to 1024
|
44
|
+
super(listen_socket, klass, *args, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class UNIXServer < Server
|
49
|
+
def initialize(path, klass = UNIXSocket, *args, &block)
|
50
|
+
super(::UNIXServer.new(*args), klass, *args, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/rev/socket.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C)2007 Tony Arcieri
|
3
|
+
# You can redistribute this under the terms of the Ruby license
|
4
|
+
# See file LICENSE for details
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'socket'
|
8
|
+
require 'resolv'
|
9
|
+
require File.dirname(__FILE__) + '/../rev'
|
10
|
+
|
11
|
+
module Rev
|
12
|
+
class Socket < BufferedIO
|
13
|
+
def self.connect(socket, *args)
|
14
|
+
new(socket, *args).instance_eval {
|
15
|
+
@connector = Connector.new(self, socket)
|
16
|
+
self
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
watcher_delegate :@connector
|
21
|
+
|
22
|
+
def attach(evloop)
|
23
|
+
raise RuntimeError, "connection failed" if @failed
|
24
|
+
|
25
|
+
if @connector
|
26
|
+
@connector.attach(evloop)
|
27
|
+
return self
|
28
|
+
end
|
29
|
+
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
# Called upon completion of a socket connection
|
34
|
+
def on_connect; end
|
35
|
+
event_callback :on_connect
|
36
|
+
|
37
|
+
# Called if a socket connection failed to complete
|
38
|
+
def on_connect_failed; end
|
39
|
+
event_callback :on_connect_failed
|
40
|
+
|
41
|
+
#########
|
42
|
+
protected
|
43
|
+
#########
|
44
|
+
|
45
|
+
class Connector < IOWatcher
|
46
|
+
def initialize(rev_socket, ruby_socket)
|
47
|
+
@rev_socket, @ruby_socket = rev_socket, ruby_socket
|
48
|
+
super(ruby_socket, :w)
|
49
|
+
end
|
50
|
+
|
51
|
+
def on_writable
|
52
|
+
evl = evloop
|
53
|
+
detach
|
54
|
+
|
55
|
+
if connect_successful?
|
56
|
+
@rev_socket.instance_eval { @connector = nil }
|
57
|
+
@rev_socket.attach(evl)
|
58
|
+
@rev_socket.on_connect
|
59
|
+
else
|
60
|
+
@rev_socket.instance_eval { @failed = true }
|
61
|
+
@rev_socket.on_connect_failed
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#######
|
66
|
+
private
|
67
|
+
#######
|
68
|
+
|
69
|
+
def connect_successful?
|
70
|
+
@ruby_socket.getsockopt(::Socket::SOL_SOCKET, ::Socket::SO_ERROR).unpack('i').first == 0
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class TCPSocket < Socket
|
76
|
+
attr_reader :remote_host, :remote_addr, :remote_port, :address_family
|
77
|
+
watcher_delegate :@resolver
|
78
|
+
|
79
|
+
# Perform a non-blocking connect to the given host and port
|
80
|
+
def self.connect(addr, port, *args)
|
81
|
+
family = nil
|
82
|
+
|
83
|
+
if (Resolv::IPv4.create(addr) rescue nil)
|
84
|
+
family = ::Socket::AF_INET
|
85
|
+
elsif(Resolv::IPv6.create(addr) rescue nil)
|
86
|
+
family = ::Socket::AF_INET6
|
87
|
+
end
|
88
|
+
|
89
|
+
if family
|
90
|
+
return super(TCPConnectSocket.new(family, addr, port), *args)
|
91
|
+
end
|
92
|
+
|
93
|
+
if host = Rev::DNSResolver.hosts(addr)
|
94
|
+
return connect(host, port, *args)
|
95
|
+
end
|
96
|
+
|
97
|
+
return allocate.instance_eval {
|
98
|
+
@remote_host, @remote_addr, @remote_port = addr, addr, port
|
99
|
+
@resolver = TCPConnectResolver.new(self, addr, port, *args)
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def initialize(socket)
|
104
|
+
unless socket.is_a?(::TCPSocket) or socket.is_a?(TCPConnectSocket)
|
105
|
+
raise TypeError, "socket must be a TCPSocket"
|
106
|
+
end
|
107
|
+
|
108
|
+
super
|
109
|
+
|
110
|
+
@address_family, @remote_port, @remote_host, @remote_addr = socket.peeraddr
|
111
|
+
end
|
112
|
+
|
113
|
+
#########
|
114
|
+
protected
|
115
|
+
#########
|
116
|
+
|
117
|
+
class TCPConnectSocket < ::Socket
|
118
|
+
def initialize(family, addr, port, host = addr)
|
119
|
+
@host, @addr, @port = host, addr, port
|
120
|
+
@address_family = nil
|
121
|
+
|
122
|
+
@socket = super(family, ::Socket::SOCK_STREAM, 0)
|
123
|
+
begin
|
124
|
+
@socket.connect_nonblock(::Socket.sockaddr_in(port, addr))
|
125
|
+
rescue Errno::EINPROGRESS
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def peeraddr
|
130
|
+
[
|
131
|
+
@address_family == ::Socket::AF_INET ? 'AF_INET' : 'AF_INET6',
|
132
|
+
@port,
|
133
|
+
@host,
|
134
|
+
@addr
|
135
|
+
]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class TCPConnectResolver < Rev::DNSResolver
|
140
|
+
def initialize(socket, host, port, *args)
|
141
|
+
@sock, @host, @port, @args = socket, host, port, args
|
142
|
+
super(host)
|
143
|
+
end
|
144
|
+
|
145
|
+
def on_success(addr)
|
146
|
+
host, port, args = @host, @port, @args
|
147
|
+
|
148
|
+
@sock.instance_eval {
|
149
|
+
# DNSResolver only supports IPv4 so we can safely assume an IPv4 address
|
150
|
+
socket = TCPConnectSocket.new(::Socket::AF_INET, addr, port, host)
|
151
|
+
initialize(socket, *args)
|
152
|
+
@connector = Connector.new(self, socket)
|
153
|
+
@resolver = nil
|
154
|
+
}
|
155
|
+
@sock.attach(evloop)
|
156
|
+
end
|
157
|
+
|
158
|
+
def on_failure
|
159
|
+
@sock.on_connect_failed
|
160
|
+
@sock.instance_eval {
|
161
|
+
@resolver = nil
|
162
|
+
@failed = true
|
163
|
+
}
|
164
|
+
return
|
165
|
+
end
|
166
|
+
|
167
|
+
alias_method :on_timeout, :on_failure
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class UNIXSocket < Socket
|
172
|
+
attr_reader :path, :address_family
|
173
|
+
|
174
|
+
# Connect to the given UNIX domain socket
|
175
|
+
def self.connect(path, *args)
|
176
|
+
new(::UNIXSocket.new(path), *args)
|
177
|
+
end
|
178
|
+
|
179
|
+
def initialize(socket)
|
180
|
+
raise ArgumentError, "socket must be a UNIXSocket" unless socket.is_a? ::UNIXSocket
|
181
|
+
|
182
|
+
super
|
183
|
+
@address_family, @path = socket.peeraddr
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C)2007 Tony Arcieri
|
3
|
+
# You can redistribute this under the terms of the Ruby license
|
4
|
+
# See file LICENSE for details
|
5
|
+
#++
|
6
|
+
|
7
|
+
require File.dirname(__FILE__) + '/../rev'
|
8
|
+
|
9
|
+
module Rev
|
10
|
+
class IOWatcher
|
11
|
+
# The actual implementation of this class resides in the C extension
|
12
|
+
# Here we metaprogram proper event_callbacks for the callback methods
|
13
|
+
# These can take a block and store it to be called when the event
|
14
|
+
# is actually fired.
|
15
|
+
|
16
|
+
event_callback :timer_watcher
|
17
|
+
end
|
18
|
+
end
|
data/lib/rev/watcher.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C)2007 Tony Arcieri
|
3
|
+
# You can redistribute this under the terms of the Ruby license
|
4
|
+
# See file LICENSE for details
|
5
|
+
#++
|
6
|
+
|
7
|
+
require File.dirname(__FILE__) + '/../rev'
|
8
|
+
|
9
|
+
module Rev
|
10
|
+
class Watcher
|
11
|
+
# Use an alternate watcher with the attach/detach/enable/disable methods
|
12
|
+
# if it is presently assigned. This is useful if you are waiting for
|
13
|
+
# an event to occur before the current watcher can be used in earnest,
|
14
|
+
# such as making an outgoing TCP connection.
|
15
|
+
def self.watcher_delegate(proxy_var)
|
16
|
+
%w{attach detach enable disable}.each do |method|
|
17
|
+
module_eval <<-EOD
|
18
|
+
def #{method}(*args)
|
19
|
+
if #{proxy_var}
|
20
|
+
#{proxy_var}.#{method}(*args)
|
21
|
+
return self
|
22
|
+
end
|
23
|
+
|
24
|
+
super
|
25
|
+
end
|
26
|
+
EOD
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Define callbacks whose behavior can be changed on-the-fly per instance.
|
31
|
+
# This is done by giving a block to the callback method, which is captured
|
32
|
+
# as a proc and stored for later. If the method is called without a block,
|
33
|
+
# the stored block is executed if present, otherwise it's a noop.
|
34
|
+
def self.event_callback(*methods)
|
35
|
+
methods.each do |method|
|
36
|
+
module_eval <<-EOD
|
37
|
+
def #{method}(*args, &block)
|
38
|
+
if block
|
39
|
+
@#{method}_callback = block
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
@#{method}_callback.(*([self] + args)) if @#{method}_callback
|
44
|
+
end
|
45
|
+
EOD
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/rev_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#
|
2
|
+
# Oops, were you expecting some real RSpec?
|
3
|
+
#
|
4
|
+
# I'm sorry to disappoint. Really, this is pretty damn weak.
|
5
|
+
#
|
6
|
+
# I swear that after Ruby 1.9 comes out proper, this will become an actual spec
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'socket'
|
10
|
+
require File.dirname(__FILE__) + '/../lib/rev'
|
11
|
+
|
12
|
+
class MyWatcher < Rev::IOWatcher
|
13
|
+
def on_readable
|
14
|
+
puts "Yippie, I'm readable!"
|
15
|
+
detach
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
listen_socket = TCPServer.new 'localhost', 4321
|
20
|
+
watcher = MyWatcher.new(listen_socket)
|
21
|
+
event_loop = Rev::Loop.new
|
22
|
+
watcher.attach(event_loop)
|
23
|
+
|
24
|
+
puts "Running the event loop in blocking mode on localhost port 4321"
|
25
|
+
puts "Telnet there or something and you should get a read event"
|
26
|
+
event_loop.run
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: rev
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-12-25 00:00:00 -07:00
|
8
|
+
summary: Ruby 1.9 binding to the libev high performance event library
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email:
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.9.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Tony Arcieri
|
31
|
+
files:
|
32
|
+
- LICENSE
|
33
|
+
- README
|
34
|
+
- lib/rev
|
35
|
+
- lib/rev/buffered_io.rb
|
36
|
+
- lib/rev/dns_resolver.rb
|
37
|
+
- lib/rev/io_watcher.rb
|
38
|
+
- lib/rev/listener.rb
|
39
|
+
- lib/rev/loop.rb
|
40
|
+
- lib/rev/server.rb
|
41
|
+
- lib/rev/socket.rb
|
42
|
+
- lib/rev/timer_watcher.rb
|
43
|
+
- lib/rev/watcher.rb
|
44
|
+
- lib/rev.rb
|
45
|
+
- ext/libev/ev.h
|
46
|
+
- ext/libev/ev_vars.h
|
47
|
+
- ext/libev/ev_wrap.h
|
48
|
+
- ext/rev/rev.h
|
49
|
+
- ext/rev/rev_watcher.h
|
50
|
+
- ext/libev/ev.c
|
51
|
+
- ext/libev/ev_epoll.c
|
52
|
+
- ext/libev/ev_kqueue.c
|
53
|
+
- ext/libev/ev_poll.c
|
54
|
+
- ext/libev/ev_port.c
|
55
|
+
- ext/libev/ev_select.c
|
56
|
+
- ext/libev/ev_win32.c
|
57
|
+
- ext/rev/rev_ext.c
|
58
|
+
- ext/rev/rev_io_watcher.c
|
59
|
+
- ext/rev/rev_loop.c
|
60
|
+
- ext/rev/rev_timer_watcher.c
|
61
|
+
- ext/rev/rev_watcher.c
|
62
|
+
- ext/rev/extconf.rb
|
63
|
+
test_files:
|
64
|
+
- spec/rev_spec.rb
|
65
|
+
rdoc_options:
|
66
|
+
- --title
|
67
|
+
- Rev
|
68
|
+
- --main
|
69
|
+
- README
|
70
|
+
- --line-numbers
|
71
|
+
extra_rdoc_files:
|
72
|
+
- README
|
73
|
+
- LICENSE
|
74
|
+
- ext/libev/ev.c
|
75
|
+
- ext/libev/ev_epoll.c
|
76
|
+
- ext/libev/ev_kqueue.c
|
77
|
+
- ext/libev/ev_poll.c
|
78
|
+
- ext/libev/ev_port.c
|
79
|
+
- ext/libev/ev_select.c
|
80
|
+
- ext/libev/ev_win32.c
|
81
|
+
- ext/rev/rev_ext.c
|
82
|
+
- ext/rev/rev_io_watcher.c
|
83
|
+
- ext/rev/rev_loop.c
|
84
|
+
- ext/rev/rev_timer_watcher.c
|
85
|
+
- ext/rev/rev_watcher.c
|
86
|
+
executables: []
|
87
|
+
|
88
|
+
extensions:
|
89
|
+
- ext/rev/extconf.rb
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
dependencies: []
|
93
|
+
|