libuv 0.10.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.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/.travis.yml +16 -0
- data/Gemfile +2 -0
- data/LICENSE +24 -0
- data/README.md +73 -0
- data/Rakefile +31 -0
- data/lib/libuv.rb +34 -0
- data/lib/libuv/assertions.rb +23 -0
- data/lib/libuv/async.rb +33 -0
- data/lib/libuv/check.rb +49 -0
- data/lib/libuv/error.rb +70 -0
- data/lib/libuv/ext/ext.rb +257 -0
- data/lib/libuv/ext/platform/darwin_x64.rb +12 -0
- data/lib/libuv/ext/platform/linux.rb +8 -0
- data/lib/libuv/ext/platform/unix.rb +14 -0
- data/lib/libuv/ext/platform/windows.rb +27 -0
- data/lib/libuv/ext/tasks.rb +27 -0
- data/lib/libuv/ext/tasks/mac.rb +23 -0
- data/lib/libuv/ext/tasks/unix.rb +23 -0
- data/lib/libuv/ext/tasks/win.rb +11 -0
- data/lib/libuv/ext/types.rb +230 -0
- data/lib/libuv/fs_event.rb +31 -0
- data/lib/libuv/handle.rb +82 -0
- data/lib/libuv/idle.rb +49 -0
- data/lib/libuv/listener.rb +34 -0
- data/lib/libuv/loop.rb +310 -0
- data/lib/libuv/net.rb +38 -0
- data/lib/libuv/pipe.rb +97 -0
- data/lib/libuv/prepare.rb +49 -0
- data/lib/libuv/q.rb +429 -0
- data/lib/libuv/resource.rb +28 -0
- data/lib/libuv/simple_async.rb +28 -0
- data/lib/libuv/stream.rb +124 -0
- data/lib/libuv/tcp.rb +194 -0
- data/lib/libuv/timer.rb +75 -0
- data/lib/libuv/tty.rb +34 -0
- data/lib/libuv/udp.rb +256 -0
- data/lib/libuv/version.rb +3 -0
- data/lib/libuv/work.rb +62 -0
- data/libuv.gemspec +54 -0
- data/spec/async_spec.rb +60 -0
- data/spec/defer_spec.rb +980 -0
- data/spec/idle_spec.rb +56 -0
- data/spec/pipe_spec.rb +148 -0
- data/spec/tcp_spec.rb +188 -0
- metadata +382 -0
data/lib/libuv/idle.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Libuv
|
2
|
+
class Idle < Handle
|
3
|
+
|
4
|
+
|
5
|
+
def initialize(loop, callback = nil, &blk)
|
6
|
+
@loop = loop
|
7
|
+
@callback = callback || blk
|
8
|
+
|
9
|
+
idle_ptr = ::Libuv::Ext.create_handle(:uv_idle)
|
10
|
+
error = check_result(::Libuv::Ext.idle_init(loop.handle, idle_ptr))
|
11
|
+
|
12
|
+
super(idle_ptr, error)
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
return if @closed
|
17
|
+
error = check_result ::Libuv::Ext.idle_start(handle, callback(:on_idle))
|
18
|
+
reject(error) if error
|
19
|
+
end
|
20
|
+
|
21
|
+
def stop
|
22
|
+
return if @closed
|
23
|
+
error = check_result ::Libuv::Ext.idle_stop(handle)
|
24
|
+
reject(error) if error
|
25
|
+
end
|
26
|
+
|
27
|
+
def progress(callback = nil, &blk)
|
28
|
+
@callback = callback || blk
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
|
35
|
+
def on_idle(handle, status)
|
36
|
+
e = check_result(status)
|
37
|
+
|
38
|
+
if e
|
39
|
+
reject(e)
|
40
|
+
else
|
41
|
+
begin
|
42
|
+
@callback.call
|
43
|
+
rescue Exception => e
|
44
|
+
@loop.log :error, :idle_cb, e
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'thread_safe'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module Libuv
|
5
|
+
module Listener
|
6
|
+
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
|
11
|
+
CALLBACKS = ThreadSafe::Cache.new
|
12
|
+
|
13
|
+
|
14
|
+
def callbacks
|
15
|
+
@callbacks ||= Set.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def callback(name)
|
19
|
+
const_name = "#{name}_#{object_id}".to_sym
|
20
|
+
unless CALLBACKS[const_name]
|
21
|
+
callbacks << const_name
|
22
|
+
CALLBACKS[const_name] = method(name)
|
23
|
+
end
|
24
|
+
CALLBACKS[const_name]
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear_callbacks
|
28
|
+
callbacks.each do |name|
|
29
|
+
CALLBACKS.delete(name)
|
30
|
+
end
|
31
|
+
callbacks.clear
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/libuv/loop.rb
ADDED
@@ -0,0 +1,310 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Libuv
|
4
|
+
class Loop
|
5
|
+
include Resource, Assertions
|
6
|
+
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
# Get default loop
|
10
|
+
#
|
11
|
+
# @return [::Libuv::Loop]
|
12
|
+
def default
|
13
|
+
create(::Libuv::Ext.default_loop)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Create new loop
|
17
|
+
#
|
18
|
+
# @return [::Libuv::Loop]
|
19
|
+
def new
|
20
|
+
create(::Libuv::Ext.loop_new)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Create custom loop from pointer
|
24
|
+
#
|
25
|
+
# @return [::Libuv::Loop]
|
26
|
+
def create(pointer)
|
27
|
+
allocate.tap { |i| i.send(:initialize, FFI::AutoPointer.new(pointer, ::Libuv::Ext.method(:loop_delete))) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
extend ClassMethods
|
31
|
+
|
32
|
+
|
33
|
+
# Initialize a loop using an FFI::Pointer
|
34
|
+
#
|
35
|
+
# @return [::Libuv::Loop]
|
36
|
+
def initialize(pointer) # :notnew:
|
37
|
+
@pointer = pointer
|
38
|
+
@loop = self
|
39
|
+
|
40
|
+
# Create an async call for scheduling work from other threads
|
41
|
+
@run_queue = Queue.new
|
42
|
+
@queue_proc = proc do
|
43
|
+
# Rubinius fix for promises
|
44
|
+
# Anything calling schedule will
|
45
|
+
# be delayed a tick outside of promise callbacks on rubinius (see https://github.com/ffi/ffi/issues/279)
|
46
|
+
#@reactor_thread = Thread.current # Should work in rubinius 2.0
|
47
|
+
|
48
|
+
# ensure we only execute what was required for this tick
|
49
|
+
length = @run_queue.length
|
50
|
+
length.times do
|
51
|
+
begin
|
52
|
+
run = @run_queue.pop true # pop non-block
|
53
|
+
run.call
|
54
|
+
rescue Exception => e
|
55
|
+
@loop.log :error, :next_tick_cb, e
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
@process_queue = SimpleAsync.new(@loop, @queue_proc)
|
60
|
+
|
61
|
+
# Create a next tick timer
|
62
|
+
@next_tick = @loop.timer do
|
63
|
+
@next_tick_scheduled = false
|
64
|
+
@queue_proc.call
|
65
|
+
end
|
66
|
+
|
67
|
+
# Create an async call for ending the loop
|
68
|
+
@stop_loop = SimpleAsync.new @loop do
|
69
|
+
@process_queue.close
|
70
|
+
@stop_loop.close
|
71
|
+
@next_tick.close
|
72
|
+
|
73
|
+
::Libuv::Ext.stop(@pointer)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def handle; @pointer; end
|
78
|
+
|
79
|
+
# Run the actual event loop. This method will block for the duration of event loop unless
|
80
|
+
# it is run inside an existing event loop, where a new thread will be created for it
|
81
|
+
#
|
82
|
+
# @param run_type [:UV_RUN_DEFAULT, :UV_RUN_ONCE, :UV_RUN_NOWAIT]
|
83
|
+
# @yieldparam promise [::Libuv::Loop] Yields a promise that can be used for logging unhandled
|
84
|
+
# exceptions on the loop.
|
85
|
+
# @return [::Libuv::Q::Promise]
|
86
|
+
def run(run_type = :UV_RUN_DEFAULT)
|
87
|
+
@loop_notify = @loop.defer
|
88
|
+
|
89
|
+
begin
|
90
|
+
@reactor_thread = Thread.current
|
91
|
+
yield @loop_notify.promise if block_given?
|
92
|
+
::Libuv::Ext.run(@pointer, run_type) # This is blocking
|
93
|
+
ensure
|
94
|
+
@reactor_thread = nil
|
95
|
+
@run_queue.clear
|
96
|
+
end
|
97
|
+
|
98
|
+
@loop
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
# Creates a deferred result object for where the result of an operation may only be returned
|
103
|
+
# at some point in the future or is being processed on a different thread (thread safe)
|
104
|
+
#
|
105
|
+
# @return [::Libuv::Q::Deferred]
|
106
|
+
def defer
|
107
|
+
Q.defer(@loop)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Combines multiple promises into a single promise that is resolved when all of the input
|
111
|
+
# promises are resolved. (thread safe)
|
112
|
+
#
|
113
|
+
# @param [*Promise] Promises a number of promises that will be combined into a single promise
|
114
|
+
# @return [Promise] Returns a single promise that will be resolved with an array of values,
|
115
|
+
# each value corresponding to the promise at the same index in the `promises` array. If any of
|
116
|
+
# the promises is resolved with a rejection, this resulting promise will be resolved with the
|
117
|
+
# same rejection.
|
118
|
+
def all(*promises)
|
119
|
+
Q.all(@loop, *promises)
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Combines multiple promises into a single promise that is resolved when any of the input
|
124
|
+
# promises are resolved.
|
125
|
+
#
|
126
|
+
# @param [*Promise] Promises a number of promises that will be combined into a single promise
|
127
|
+
# @return [Promise] Returns a single promise
|
128
|
+
def any(*promises)
|
129
|
+
Q.any(@loop, *promises)
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Combines multiple promises into a single promise that is resolved when all of the input
|
134
|
+
# promises are resolved or rejected.
|
135
|
+
#
|
136
|
+
# @param [*Promise] Promises a number of promises that will be combined into a single promise
|
137
|
+
# @return [Promise] Returns a single promise that will be resolved with an array of values,
|
138
|
+
# each [result, wasResolved] value pair corresponding to a at the same index in the `promises` array.
|
139
|
+
def finally(*promises)
|
140
|
+
Q.finally(@loop, *promises)
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
# forces loop time update, useful for getting more granular times
|
145
|
+
#
|
146
|
+
# @return nil
|
147
|
+
def update_time
|
148
|
+
::Libuv::Ext.update_time(@pointer)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Get current time in microseconds
|
152
|
+
#
|
153
|
+
# @return [Fixnum]
|
154
|
+
def now
|
155
|
+
::Libuv::Ext.now(@pointer)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Lookup an error code and return is as an error object
|
159
|
+
#
|
160
|
+
# @param err [Integer] The error code to look up.
|
161
|
+
# @return [::Libuv::Error]
|
162
|
+
def lookup_error(err)
|
163
|
+
name = ::Libuv::Ext.err_name(err)
|
164
|
+
msg = ::Libuv::Ext.strerror(err)
|
165
|
+
|
166
|
+
::Libuv::Error.const_get(name.to_sym).new(msg)
|
167
|
+
rescue Exception => e
|
168
|
+
@loop.log :warn, :error_lookup_failed, e
|
169
|
+
::Libuv::Error::UNKNOWN.new("error lookup failed for code #{err} #{name} #{msg}")
|
170
|
+
end
|
171
|
+
|
172
|
+
# Get a new TCP instance
|
173
|
+
#
|
174
|
+
# @return [::Libuv::TCP]
|
175
|
+
def tcp
|
176
|
+
TCP.new(@loop)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Get a new UDP instance
|
180
|
+
#
|
181
|
+
# @return [::Libuv::UDP]
|
182
|
+
def udp
|
183
|
+
UDP.new(@loop)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Get a new TTY instance
|
187
|
+
#
|
188
|
+
# @param fileno [Integer] Integer file descriptor of a tty device
|
189
|
+
# @param readable [true, false] Boolean indicating if TTY is readable
|
190
|
+
# @return [::Libuv::TTY]
|
191
|
+
def tty(fileno, readable = false)
|
192
|
+
assert_type(Integer, fileno, "io#fileno must return an integer file descriptor, #{fileno.inspect} given")
|
193
|
+
|
194
|
+
TTY.new(@loop, fileno, readable)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Get a new Pipe instance
|
198
|
+
#
|
199
|
+
# @param ipc [true, false]
|
200
|
+
# indicate if a handle will be used for ipc, useful for sharing tcp socket between processes
|
201
|
+
# @return [::Libuv::Pipe]
|
202
|
+
def pipe(ipc = false)
|
203
|
+
Pipe.new(@loop, ipc)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Get a new timer instance
|
207
|
+
#
|
208
|
+
# @return [::Libuv::Timer]
|
209
|
+
def timer(callback = nil, &blk)
|
210
|
+
Timer.new(@loop, callback || blk)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Get a new Prepare handle
|
214
|
+
#
|
215
|
+
# @return [::Libuv::Prepare]
|
216
|
+
def prepare
|
217
|
+
Prepare.new(@loop)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Get a new Check handle
|
221
|
+
#
|
222
|
+
# @return [::Libuv::Check]
|
223
|
+
def check
|
224
|
+
Check.new(@loop)
|
225
|
+
end
|
226
|
+
|
227
|
+
# Get a new Idle handle
|
228
|
+
#
|
229
|
+
# @return [::Libuv::Idle]
|
230
|
+
def idle(callback = nil, &block)
|
231
|
+
Idle.new(@loop, callback || block)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Get a new Async handle
|
235
|
+
#
|
236
|
+
# @return [::Libuv::Async]
|
237
|
+
def async(callback = nil, &block)
|
238
|
+
callback ||= block
|
239
|
+
handle = Async.new(@loop)
|
240
|
+
handle.progress callback if callback
|
241
|
+
handle
|
242
|
+
end
|
243
|
+
|
244
|
+
# Queue some work for processing in the libuv thread pool
|
245
|
+
#
|
246
|
+
# @return [::Libuv::Work]
|
247
|
+
# @raise [ArgumentError] if block is not given
|
248
|
+
def work(callback = nil, &block)
|
249
|
+
Work.new(@loop, callback || block) # Work is a promise object
|
250
|
+
end
|
251
|
+
|
252
|
+
# Get a new FSEvent instance
|
253
|
+
#
|
254
|
+
# @return [::Libuv::FSEvent]
|
255
|
+
def fs_event(path)
|
256
|
+
assert_type(String, path)
|
257
|
+
FSEvent.new(@loop, path)
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
# Schedule some work to be processed on the event loop (thread safe)
|
262
|
+
#
|
263
|
+
# @return [nil]
|
264
|
+
def schedule(&block)
|
265
|
+
assert_block(block)
|
266
|
+
|
267
|
+
if @reactor_thread == Thread.current
|
268
|
+
block.call
|
269
|
+
else
|
270
|
+
@run_queue << block
|
271
|
+
@process_queue.call
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# Schedule some work to be processed in the next iteration of the event loop (thread safe)
|
276
|
+
#
|
277
|
+
# @return [nil]
|
278
|
+
def next_tick(&block)
|
279
|
+
assert_block(block)
|
280
|
+
|
281
|
+
@run_queue << block
|
282
|
+
if @reactor_thread == Thread.current
|
283
|
+
# Create a next tick timer
|
284
|
+
if not @next_tick_scheduled
|
285
|
+
@next_tick.start(0)
|
286
|
+
@next_tick_scheduled = true
|
287
|
+
end
|
288
|
+
else
|
289
|
+
@process_queue.call
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
# Notifies the loop there was an event that should be logged
|
294
|
+
#
|
295
|
+
# @param level [Symbol] the error level (info, warn, error etc)
|
296
|
+
# @param id [Object] some kind of identifying information
|
297
|
+
# @param *args [*args] any additional information
|
298
|
+
# @return [nil]
|
299
|
+
def log(level, id, *args)
|
300
|
+
@loop_notify.notify(level, id, *args)
|
301
|
+
end
|
302
|
+
|
303
|
+
# Closes handles opened by the loop class and completes the current loop iteration (thread safe)
|
304
|
+
#
|
305
|
+
# @return [nil]
|
306
|
+
def stop
|
307
|
+
@stop_loop.call
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
data/lib/libuv/net.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Libuv
|
4
|
+
module Net
|
5
|
+
|
6
|
+
|
7
|
+
IP_ARGUMENT_ERROR = "ip must be a String".freeze # Arguments specifying an IP address
|
8
|
+
PORT_ARGUMENT_ERROR = "port must be an Integer".freeze # Arguments specifying an IP port
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
|
14
|
+
def get_sockaddr_and_len
|
15
|
+
sockaddr = FFI::MemoryPointer.new(UV::Sockaddr)
|
16
|
+
len = FFI::MemoryPointer.new(:int)
|
17
|
+
len.put_int(0, UV::Sockaddr.size)
|
18
|
+
[sockaddr, len]
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_ip_and_port(sockaddr, len=nil)
|
22
|
+
if sockaddr[:sa_family] == Socket::Constants::AF_INET6
|
23
|
+
len ||= Socket::Constants::INET6_ADDRSTRLEN
|
24
|
+
sockaddr_in6 = UV::SockaddrIn6.new(sockaddr.pointer)
|
25
|
+
ip_ptr = FFI::MemoryPointer.new(:char, len)
|
26
|
+
::Libuv::Ext.ip6_name(sockaddr_in6, ip_ptr, len)
|
27
|
+
port = ::Libuv::Ext.ntohs(sockaddr_in6[:sin6_port])
|
28
|
+
else
|
29
|
+
len ||= Socket::Constants::INET_ADDRSTRLEN
|
30
|
+
sockaddr_in = UV::SockaddrIn.new(sockaddr.pointer)
|
31
|
+
ip_ptr = FFI::MemoryPointer.new(:char, len)
|
32
|
+
::Libuv::Ext.ip4_name(sockaddr_in, ip_ptr, len)
|
33
|
+
port = ::Libuv::Ext.ntohs(sockaddr_in[:sin_port])
|
34
|
+
end
|
35
|
+
[ip_ptr.read_string, port]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/libuv/pipe.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
module Libuv
|
2
|
+
class Pipe < Handle
|
3
|
+
include Stream
|
4
|
+
|
5
|
+
|
6
|
+
def initialize(loop, ipc, acceptor = nil)
|
7
|
+
@loop, @ipc = loop, ipc
|
8
|
+
|
9
|
+
pipe_ptr = ::Libuv::Ext.create_handle(:uv_pipe)
|
10
|
+
error = check_result(::Libuv::Ext.pipe_init(loop.handle, pipe_ptr, ipc ? 1 : 0))
|
11
|
+
error = check_result(::Libuv::Ext.accept(acceptor, pipe_ptr)) if acceptor && error.nil?
|
12
|
+
|
13
|
+
super(pipe_ptr, error)
|
14
|
+
end
|
15
|
+
|
16
|
+
def bind(name, callback = nil, &blk)
|
17
|
+
@on_listen = callback || blk
|
18
|
+
assert_type(String, name, "name must be a String")
|
19
|
+
name = windows_path name if FFI::Platform.windows?
|
20
|
+
|
21
|
+
error = check_result ::Libuv::Ext.pipe_bind(handle, name)
|
22
|
+
reject(error) if error
|
23
|
+
end
|
24
|
+
|
25
|
+
def accept(callback = nil, &blk)
|
26
|
+
pipe = nil
|
27
|
+
begin
|
28
|
+
pipe = Pipe.new(loop, @ipc, handle)
|
29
|
+
rescue Exception => e
|
30
|
+
@loop.log :info, :pipe_accept_failed, e
|
31
|
+
end
|
32
|
+
if pipe
|
33
|
+
begin
|
34
|
+
(callback || blk).call(pipe)
|
35
|
+
rescue Exception => e
|
36
|
+
@loop.log :error, :pipe_accept_cb, e
|
37
|
+
end
|
38
|
+
end
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def open(fileno, callback = nil, &blk)
|
43
|
+
@callback = callback || blk
|
44
|
+
assert_type(Integer, fileno, "io#fileno must return an integer file descriptor")
|
45
|
+
begin
|
46
|
+
check_result! ::Libuv::Ext.pipe_open(handle, fileno)
|
47
|
+
|
48
|
+
# Emulate on_connect behavior
|
49
|
+
begin
|
50
|
+
@callback.call(self)
|
51
|
+
rescue Exception => e
|
52
|
+
@loop.log :error, :pipe_connect_cb, e
|
53
|
+
end
|
54
|
+
rescue Exception => e
|
55
|
+
reject(e)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def connect(name, callback = nil, &blk)
|
60
|
+
@callback = callback || blk
|
61
|
+
assert_type(String, name, "name must be a String")
|
62
|
+
begin
|
63
|
+
name = windows_path name if FFI::Platform.windows?
|
64
|
+
::Libuv::Ext.pipe_connect(::Libuv::Ext.create_request(:uv_connect), handle, name, callback(:on_connect))
|
65
|
+
rescue Exception => e
|
66
|
+
reject(e)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Windows only
|
71
|
+
def pending_instances=(count)
|
72
|
+
assert_type(Integer, count, "count must be an Integer")
|
73
|
+
::Libuv::Ext.pipe_pending_instances(handle, count)
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
|
80
|
+
def on_connect(req, status)
|
81
|
+
::Libuv::Ext.free(req)
|
82
|
+
begin
|
83
|
+
@callback.call(self)
|
84
|
+
rescue Exception => e
|
85
|
+
@loop.log :error, :pipe_connect_cb, e
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def windows_path(name)
|
90
|
+
# test for \\\\.\\pipe
|
91
|
+
if not name =~ /(\/|\\){2}\.(\/|\\)pipe/i
|
92
|
+
name = ::File.join("\\\\.\\pipe", name)
|
93
|
+
end
|
94
|
+
name.gsub("/", "\\")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|