libuv 0.10.0 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -17
- data/.gitmodules +3 -3
- data/.rspec +1 -1
- data/.travis.yml +16 -16
- data/Gemfile +2 -2
- data/LICENSE +23 -23
- data/README.md +82 -73
- data/Rakefile +31 -31
- data/lib/libuv.rb +53 -34
- data/lib/libuv/async.rb +47 -33
- data/lib/libuv/check.rb +55 -48
- data/lib/libuv/error.rb +70 -70
- data/lib/libuv/ext/ext.rb +264 -256
- data/lib/libuv/ext/platform/darwin_x64.rb +12 -12
- data/lib/libuv/ext/platform/linux.rb +7 -7
- data/lib/libuv/ext/platform/unix.rb +13 -13
- data/lib/libuv/ext/platform/windows.rb +26 -26
- data/lib/libuv/ext/tasks.rb +27 -27
- data/lib/libuv/ext/tasks/mac.rb +23 -23
- data/lib/libuv/ext/tasks/unix.rb +23 -23
- data/lib/libuv/ext/tasks/win.rb +11 -11
- data/lib/libuv/ext/types.rb +234 -229
- data/lib/libuv/file.rb +192 -0
- data/lib/libuv/filesystem.rb +233 -0
- data/lib/libuv/fs_event.rb +31 -31
- data/lib/libuv/handle.rb +85 -81
- data/lib/libuv/idle.rb +56 -49
- data/lib/libuv/loop.rb +338 -310
- data/lib/libuv/{assertions.rb → mixins/assertions.rb} +23 -23
- data/lib/libuv/mixins/fs_checks.rb +55 -0
- data/lib/libuv/{listener.rb → mixins/listener.rb} +34 -34
- data/lib/libuv/{net.rb → mixins/net.rb} +37 -37
- data/lib/libuv/{resource.rb → mixins/resource.rb} +27 -27
- data/lib/libuv/{stream.rb → mixins/stream.rb} +143 -123
- data/lib/libuv/pipe.rb +197 -97
- data/lib/libuv/prepare.rb +56 -49
- data/lib/libuv/q.rb +1 -1
- data/lib/libuv/signal.rb +51 -0
- data/lib/libuv/tcp.rb +204 -193
- data/lib/libuv/timer.rb +88 -75
- data/lib/libuv/tty.rb +37 -34
- data/lib/libuv/udp.rb +273 -255
- data/lib/libuv/version.rb +3 -3
- data/lib/libuv/work.rb +63 -61
- data/libuv.gemspec +54 -54
- data/spec/async_spec.rb +60 -60
- data/spec/cpu_spec.rb +10 -0
- data/spec/defer_spec.rb +980 -980
- data/spec/filesystem_spec.rb +119 -0
- data/spec/idle_spec.rb +56 -56
- data/spec/pipe_spec.rb +153 -148
- data/spec/tcp_spec.rb +203 -188
- metadata +73 -49
- checksums.yaml +0 -15
- data/lib/libuv/simple_async.rb +0 -28
@@ -1,23 +1,23 @@
|
|
1
|
-
module Libuv
|
2
|
-
module Assertions
|
3
|
-
MSG_NO_PROC = 'no block given'
|
4
|
-
|
5
|
-
def assert_block(proc, msg = MSG_NO_PROC)
|
6
|
-
raise ArgumentError, msg, caller if proc.nil?
|
7
|
-
end
|
8
|
-
|
9
|
-
def assert_type(type, actual, msg = nil)
|
10
|
-
if not actual.kind_of?(type)
|
11
|
-
msg ||= "value #{actual.inspect} is not a valid #{type}"
|
12
|
-
raise ArgumentError, msg, caller
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def assert_boolean(actual, msg = nil)
|
17
|
-
if not (actual.kind_of?(TrueClass) || actual.kind_of?(FalseClass))
|
18
|
-
msg ||= "value #{actual.inspect} is not a valid Boolean"
|
19
|
-
raise ArgumentError, msg, caller
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
1
|
+
module Libuv
|
2
|
+
module Assertions
|
3
|
+
MSG_NO_PROC = 'no block given'
|
4
|
+
|
5
|
+
def assert_block(proc, msg = MSG_NO_PROC)
|
6
|
+
raise ArgumentError, msg, caller if proc.nil?
|
7
|
+
end
|
8
|
+
|
9
|
+
def assert_type(type, actual, msg = nil)
|
10
|
+
if not actual.kind_of?(type)
|
11
|
+
msg ||= "value #{actual.inspect} is not a valid #{type}"
|
12
|
+
raise ArgumentError, msg, caller
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_boolean(actual, msg = nil)
|
17
|
+
if not (actual.kind_of?(TrueClass) || actual.kind_of?(FalseClass))
|
18
|
+
msg ||= "value #{actual.inspect} is not a valid Boolean"
|
19
|
+
raise ArgumentError, msg, caller
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
module Libuv
|
3
|
+
module FsChecks
|
4
|
+
|
5
|
+
|
6
|
+
def stat
|
7
|
+
@stat_deferred = @loop.defer
|
8
|
+
|
9
|
+
request = ::Libuv::Ext.create_request(:uv_fs)
|
10
|
+
pre_check @stat_deferred, request, ::Libuv::Ext.fs_fstat(@loop.handle, request, @fileno, callback(:on_stat))
|
11
|
+
@stat_deferred.promise
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
|
18
|
+
def on_stat(req)
|
19
|
+
if post_check(req, @stat_deferred)
|
20
|
+
uv_stat = req[:stat]
|
21
|
+
uv_members = uv_stat.members
|
22
|
+
values = UvStat.members.map { |k| uv_members.include?(k) ? uv_stat[k] : nil }
|
23
|
+
uv_stat = UvStat.new(*values)
|
24
|
+
|
25
|
+
cleanup(req)
|
26
|
+
@stat_deferred.resolve(uv_stat)
|
27
|
+
end
|
28
|
+
@stat_deferred = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def pre_check(deferrable, request, result)
|
32
|
+
error = check_result result
|
33
|
+
if error
|
34
|
+
::Libuv::Ext.free(request)
|
35
|
+
deferrable.reject(error)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def cleanup(req)
|
40
|
+
::Libuv::Ext.fs_req_cleanup(req)
|
41
|
+
::Libuv::Ext.free(req)
|
42
|
+
end
|
43
|
+
|
44
|
+
def post_check(req, deferrable)
|
45
|
+
error = check_result(req[:result])
|
46
|
+
if error
|
47
|
+
cleanup(req)
|
48
|
+
deferrable.reject(error)
|
49
|
+
false
|
50
|
+
else
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,34 +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
|
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
|
@@ -1,38 +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
|
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
38
|
end
|
@@ -1,28 +1,28 @@
|
|
1
|
-
module Libuv
|
2
|
-
module Resource
|
3
|
-
|
4
|
-
|
5
|
-
def resolve(deferred, rc)
|
6
|
-
if rc.nil? || rc >= 0
|
7
|
-
deferred.resolve(nil)
|
8
|
-
else
|
9
|
-
deferred.reject(@loop.lookup_error(rc))
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def check_result!(rc)
|
14
|
-
e = @loop.lookup_error(rc) unless rc.nil? || rc >= 0
|
15
|
-
raise e if e
|
16
|
-
end
|
17
|
-
|
18
|
-
def check_result(rc)
|
19
|
-
@loop.lookup_error(rc) unless rc.nil? || rc >= 0
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_ptr
|
23
|
-
@pointer
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
end
|
1
|
+
module Libuv
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
|
5
|
+
def resolve(deferred, rc)
|
6
|
+
if rc.nil? || rc >= 0
|
7
|
+
deferred.resolve(nil)
|
8
|
+
else
|
9
|
+
deferred.reject(@loop.lookup_error(rc))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_result!(rc)
|
14
|
+
e = @loop.lookup_error(rc) unless rc.nil? || rc >= 0
|
15
|
+
raise e if e
|
16
|
+
end
|
17
|
+
|
18
|
+
def check_result(rc)
|
19
|
+
@loop.lookup_error(rc) unless rc.nil? || rc >= 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_ptr
|
23
|
+
@pointer
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
28
|
end
|
@@ -1,124 +1,144 @@
|
|
1
|
-
module Libuv
|
2
|
-
module Stream
|
3
|
-
|
4
|
-
|
5
|
-
BACKLOG_ERROR = "backlog must be an Integer".freeze
|
6
|
-
WRITE_ERROR = "data must be a String".freeze
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
deferred
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
e
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
1
|
+
module Libuv
|
2
|
+
module Stream
|
3
|
+
|
4
|
+
|
5
|
+
BACKLOG_ERROR = "backlog must be an Integer".freeze
|
6
|
+
WRITE_ERROR = "data must be a String".freeze
|
7
|
+
STREAM_CLOSED_ERROR = "unable to write to a closed stream".freeze
|
8
|
+
CLOSED_HANDLE_ERROR = "handle closed before accept called".freeze
|
9
|
+
|
10
|
+
|
11
|
+
def listen(backlog)
|
12
|
+
return if @closed
|
13
|
+
assert_type(Integer, backlog, BACKLOG_ERROR)
|
14
|
+
error = check_result ::Libuv::Ext.listen(handle, Integer(backlog), callback(:on_listen))
|
15
|
+
reject(error) if error
|
16
|
+
end
|
17
|
+
|
18
|
+
# Starts reading from the handle
|
19
|
+
def start_read
|
20
|
+
return if @closed
|
21
|
+
error = check_result ::Libuv::Ext.read_start(handle, callback(:on_allocate), callback(:on_read))
|
22
|
+
reject(error) if error
|
23
|
+
end
|
24
|
+
|
25
|
+
# Stops reading from the handle
|
26
|
+
def stop_read
|
27
|
+
return if @closed
|
28
|
+
error = check_result ::Libuv::Ext.read_stop(handle)
|
29
|
+
reject(error) if error
|
30
|
+
end
|
31
|
+
|
32
|
+
# Shutsdown the writes on the handle waiting until the last write is complete before triggering the callback
|
33
|
+
def shutdown
|
34
|
+
return if @closed
|
35
|
+
error = check_result ::Libuv::Ext.shutdown(::Libuv::Ext.create_request(:uv_shutdown), handle, callback(:on_shutdown))
|
36
|
+
reject(error) if error
|
37
|
+
end
|
38
|
+
|
39
|
+
def write(data)
|
40
|
+
# NOTE:: Similar to udp.rb -> write
|
41
|
+
deferred = @loop.defer
|
42
|
+
if !@closed
|
43
|
+
begin
|
44
|
+
assert_type(String, data, WRITE_ERROR)
|
45
|
+
|
46
|
+
size = data.respond_to?(:bytesize) ? data.bytesize : data.size
|
47
|
+
buffer = ::Libuv::Ext.buf_init(FFI::MemoryPointer.from_string(data), size)
|
48
|
+
|
49
|
+
# local as this variable will be avaliable until the handle is closed
|
50
|
+
@write_callbacks ||= []
|
51
|
+
|
52
|
+
#
|
53
|
+
# create the curried callback
|
54
|
+
#
|
55
|
+
callback = FFI::Function.new(:void, [:pointer, :int]) do |req, status|
|
56
|
+
::Libuv::Ext.free(req)
|
57
|
+
# remove the callback from the array
|
58
|
+
# assumes writes are done in order
|
59
|
+
promise = @write_callbacks.shift[0]
|
60
|
+
resolve promise, status
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
@write_callbacks << [deferred, callback]
|
65
|
+
req = ::Libuv::Ext.create_request(:uv_write)
|
66
|
+
error = check_result ::Libuv::Ext.write(req, handle, buffer, 1, callback)
|
67
|
+
|
68
|
+
if error
|
69
|
+
@write_callbacks.pop
|
70
|
+
::Libuv::Ext.free(req)
|
71
|
+
deferred.reject(error)
|
72
|
+
|
73
|
+
reject(error) # close the handle
|
74
|
+
end
|
75
|
+
rescue Exception => e
|
76
|
+
deferred.reject(e) # this write exception may not be fatal
|
77
|
+
end
|
78
|
+
else
|
79
|
+
deferred.reject(RuntimeError.new(STREAM_CLOSED_ERROR))
|
80
|
+
end
|
81
|
+
deferred.promise
|
82
|
+
end
|
83
|
+
|
84
|
+
def readable?
|
85
|
+
return false if @closed
|
86
|
+
::Libuv::Ext.is_readable(handle) > 0
|
87
|
+
end
|
88
|
+
|
89
|
+
def writable?
|
90
|
+
return false if @closed
|
91
|
+
::Libuv::Ext.is_writable(handle) > 0
|
92
|
+
end
|
93
|
+
|
94
|
+
def progress(callback = nil, &blk)
|
95
|
+
@progress = callback || blk
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
|
102
|
+
def on_listen(server, status)
|
103
|
+
e = check_result(status)
|
104
|
+
|
105
|
+
if e
|
106
|
+
reject(e) # is this cause for closing the handle?
|
107
|
+
else
|
108
|
+
begin
|
109
|
+
@on_listen.call(self)
|
110
|
+
rescue Exception => e
|
111
|
+
@loop.log :error, :stream_listen_cb, e
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def on_allocate(client, suggested_size)
|
117
|
+
::Libuv::Ext.buf_init(::Libuv::Ext.malloc(suggested_size), suggested_size)
|
118
|
+
end
|
119
|
+
|
120
|
+
def on_read(handle, nread, buf)
|
121
|
+
e = check_result(nread)
|
122
|
+
base = buf[:base]
|
123
|
+
|
124
|
+
if e
|
125
|
+
::Libuv::Ext.free(base)
|
126
|
+
reject(e)
|
127
|
+
else
|
128
|
+
data = base.read_string(nread)
|
129
|
+
::Libuv::Ext.free(base)
|
130
|
+
begin
|
131
|
+
@progress.call data, self
|
132
|
+
rescue Exception => e
|
133
|
+
@loop.log :error, :stream_progress_cb, e
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def on_shutdown(req, status)
|
139
|
+
::Libuv::Ext.free(req)
|
140
|
+
@close_error = check_result(status)
|
141
|
+
close
|
142
|
+
end
|
143
|
+
end
|
124
144
|
end
|