libuv 0.10.0 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +17 -17
  2. data/.gitmodules +3 -3
  3. data/.rspec +1 -1
  4. data/.travis.yml +16 -16
  5. data/Gemfile +2 -2
  6. data/LICENSE +23 -23
  7. data/README.md +82 -73
  8. data/Rakefile +31 -31
  9. data/lib/libuv.rb +53 -34
  10. data/lib/libuv/async.rb +47 -33
  11. data/lib/libuv/check.rb +55 -48
  12. data/lib/libuv/error.rb +70 -70
  13. data/lib/libuv/ext/ext.rb +264 -256
  14. data/lib/libuv/ext/platform/darwin_x64.rb +12 -12
  15. data/lib/libuv/ext/platform/linux.rb +7 -7
  16. data/lib/libuv/ext/platform/unix.rb +13 -13
  17. data/lib/libuv/ext/platform/windows.rb +26 -26
  18. data/lib/libuv/ext/tasks.rb +27 -27
  19. data/lib/libuv/ext/tasks/mac.rb +23 -23
  20. data/lib/libuv/ext/tasks/unix.rb +23 -23
  21. data/lib/libuv/ext/tasks/win.rb +11 -11
  22. data/lib/libuv/ext/types.rb +234 -229
  23. data/lib/libuv/file.rb +192 -0
  24. data/lib/libuv/filesystem.rb +233 -0
  25. data/lib/libuv/fs_event.rb +31 -31
  26. data/lib/libuv/handle.rb +85 -81
  27. data/lib/libuv/idle.rb +56 -49
  28. data/lib/libuv/loop.rb +338 -310
  29. data/lib/libuv/{assertions.rb → mixins/assertions.rb} +23 -23
  30. data/lib/libuv/mixins/fs_checks.rb +55 -0
  31. data/lib/libuv/{listener.rb → mixins/listener.rb} +34 -34
  32. data/lib/libuv/{net.rb → mixins/net.rb} +37 -37
  33. data/lib/libuv/{resource.rb → mixins/resource.rb} +27 -27
  34. data/lib/libuv/{stream.rb → mixins/stream.rb} +143 -123
  35. data/lib/libuv/pipe.rb +197 -97
  36. data/lib/libuv/prepare.rb +56 -49
  37. data/lib/libuv/q.rb +1 -1
  38. data/lib/libuv/signal.rb +51 -0
  39. data/lib/libuv/tcp.rb +204 -193
  40. data/lib/libuv/timer.rb +88 -75
  41. data/lib/libuv/tty.rb +37 -34
  42. data/lib/libuv/udp.rb +273 -255
  43. data/lib/libuv/version.rb +3 -3
  44. data/lib/libuv/work.rb +63 -61
  45. data/libuv.gemspec +54 -54
  46. data/spec/async_spec.rb +60 -60
  47. data/spec/cpu_spec.rb +10 -0
  48. data/spec/defer_spec.rb +980 -980
  49. data/spec/filesystem_spec.rb +119 -0
  50. data/spec/idle_spec.rb +56 -56
  51. data/spec/pipe_spec.rb +153 -148
  52. data/spec/tcp_spec.rb +203 -188
  53. metadata +73 -49
  54. checksums.yaml +0 -15
  55. data/lib/libuv/simple_async.rb +0 -28
data/lib/libuv/pipe.rb CHANGED
@@ -1,97 +1,197 @@
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
1
+ module Libuv
2
+ class Pipe < Handle
3
+ include Stream
4
+
5
+
6
+ WRITE2_ERROR = "data must be a String".freeze
7
+
8
+
9
+ def initialize(loop, ipc, acceptor = nil)
10
+ @loop, @ipc = loop, ipc
11
+
12
+ pipe_ptr = ::Libuv::Ext.create_handle(:uv_pipe)
13
+ error = check_result(::Libuv::Ext.pipe_init(loop.handle, pipe_ptr, ipc ? 1 : 0))
14
+ error = check_result(::Libuv::Ext.accept(acceptor, pipe_ptr)) if acceptor && error.nil?
15
+
16
+ super(pipe_ptr, error)
17
+ end
18
+
19
+ def bind(name, callback = nil, &blk)
20
+ return if @closed
21
+ @on_listen = callback || blk
22
+ assert_type(String, name, "name must be a String")
23
+ name = windows_path name if FFI::Platform.windows?
24
+
25
+ error = check_result ::Libuv::Ext.pipe_bind(handle, name)
26
+ reject(error) if error
27
+ end
28
+
29
+ def accept(callback = nil, &blk)
30
+ pipe = nil
31
+ begin
32
+ raise RuntimeError, CLOSED_HANDLE_ERROR if @closed
33
+ pipe = Pipe.new(loop, @ipc, handle)
34
+ rescue Exception => e
35
+ @loop.log :info, :pipe_accept_failed, e
36
+ end
37
+ if pipe
38
+ begin
39
+ (callback || blk).call(pipe)
40
+ rescue Exception => e
41
+ @loop.log :error, :pipe_accept_cb, e
42
+ end
43
+ end
44
+ nil
45
+ end
46
+
47
+ def open(fileno, callback = nil, &blk)
48
+ @callback = callback || blk
49
+ assert_type(Integer, fileno, "io#fileno must return an integer file descriptor")
50
+ begin
51
+ raise RuntimeError, CLOSED_HANDLE_ERROR if @closed
52
+ check_result! ::Libuv::Ext.pipe_open(handle, fileno)
53
+
54
+ # Emulate on_connect behavior
55
+ begin
56
+ @callback.call(self)
57
+ rescue Exception => e
58
+ @loop.log :error, :pipe_connect_cb, e
59
+ end
60
+ rescue Exception => e
61
+ reject(e)
62
+ end
63
+ end
64
+
65
+ def connect(name, callback = nil, &blk)
66
+ return if @closed
67
+ @callback = callback || blk
68
+ assert_type(String, name, "name must be a String")
69
+ begin
70
+ name = windows_path name if FFI::Platform.windows?
71
+ ::Libuv::Ext.pipe_connect(::Libuv::Ext.create_request(:uv_connect), handle, name, callback(:on_connect))
72
+ rescue Exception => e
73
+ reject(e)
74
+ end
75
+ end
76
+
77
+ def write2(fd, data = ".")
78
+ deferred = @loop.defer
79
+ if @ipc && !@closed
80
+ begin
81
+ assert_type(String, data, WRITE_ERROR)
82
+ assert_type(Handle, fd, WRITE2_ERROR)
83
+
84
+ size = data.respond_to?(:bytesize) ? data.bytesize : data.size
85
+ buffer = ::Libuv::Ext.buf_init(FFI::MemoryPointer.from_string(data), size)
86
+
87
+ # local as this variable will be avaliable until the handle is closed
88
+ @write_callbacks = @write_callbacks || []
89
+
90
+ #
91
+ # create the curried callback
92
+ #
93
+ callback = FFI::Function.new(:void, [:pointer, :int]) do |req, status|
94
+ ::Libuv::Ext.free(req)
95
+ # remove the callback from the array
96
+ # assumes writes are done in order
97
+ promise = @write_callbacks.shift[0]
98
+ resolve promise, status
99
+ end
100
+
101
+
102
+ @write_callbacks << [deferred, callback]
103
+ req = ::Libuv::Ext.create_request(:uv_write)
104
+ error = check_result ::Libuv::Ext.write2(req, handle, buffer, 1, fd.handle, callback)
105
+
106
+ if error
107
+ @write_callbacks.pop
108
+ ::Libuv::Ext.free(req)
109
+ deferred.reject(error)
110
+
111
+ reject(error) # close the handle
112
+ end
113
+ rescue Exception => e
114
+ deferred.reject(e) # this write exception may not be fatal
115
+ end
116
+ else
117
+ deferred.reject(TypeError.new('pipe not initialized for interprocess communication'))
118
+ end
119
+ deferred.promise
120
+ end
121
+
122
+ def start_read2
123
+ return if @closed
124
+ error = check_result ::Libuv::Ext.read2_start(handle, callback(:on_allocate), callback(:on_read2))
125
+ reject(error) if error
126
+ end
127
+
128
+ # Windows only
129
+ def pending_instances=(count)
130
+ return 0 if @closed
131
+ assert_type(Integer, count, "count must be an Integer")
132
+ ::Libuv::Ext.pipe_pending_instances(handle, count)
133
+ end
134
+
135
+
136
+ private
137
+
138
+
139
+ def on_connect(req, status)
140
+ ::Libuv::Ext.free(req)
141
+ begin
142
+ @callback.call(self)
143
+ rescue Exception => e
144
+ @loop.log :error, :pipe_connect_cb, e
145
+ end
146
+ end
147
+
148
+ def on_read2(handle, nread, buf, pending)
149
+ if pending != :uv_unknown_handle
150
+ # similar to regular read in stream
151
+ e = check_result(nread)
152
+ base = buf[:base]
153
+
154
+ if e
155
+ ::Libuv::Ext.free(base)
156
+ reject(e)
157
+ else
158
+ data = base.read_string(nread)
159
+ ::Libuv::Ext.free(base)
160
+
161
+ # Hide the accept logic
162
+ remote = nil
163
+ begin
164
+ case pending
165
+ when :uv_tcp
166
+ remote = TCP.new(loop, handle)
167
+ when :uv_pipe
168
+ remote = Pipe.new(loop, @ipc, handle)
169
+ else
170
+ raise NotImplementedError, "IPC for handle #{pending} not supported"
171
+ end
172
+ rescue Exception => e
173
+ remote = nil
174
+ @loop.log :info, :pipe_read2_failed, e
175
+ reject(e) # if accept fails we should close the socket to avoid a stale pipe
176
+ end
177
+ if remote
178
+ # stream the data and new socket
179
+ begin
180
+ @progress.call data, remote
181
+ rescue Exception => e
182
+ @loop.log :error, :stream_progress_cb, e
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+
189
+ def windows_path(name)
190
+ # test for \\\\.\\pipe
191
+ if not name =~ /(\/|\\){2}\.(\/|\\)pipe/i
192
+ name = ::File.join("\\\\.\\pipe", name)
193
+ end
194
+ name.gsub("/", "\\")
195
+ end
196
+ end
197
+ end
data/lib/libuv/prepare.rb CHANGED
@@ -1,49 +1,56 @@
1
- module Libuv
2
- class Prepare < Handle
3
-
4
-
5
- def initialize(loop, callback = nil, &blk)
6
- @loop = loop
7
- @callback = callback || blk
8
-
9
- prepare_ptr = ::Libuv::Ext.create_handle(:uv_prepare)
10
- error = check_result(::Libuv::Ext.prepare_init(@pointer, prepare_ptr))
11
-
12
- super(prepare_ptr, error)
13
- end
14
-
15
- def start
16
- return if @closed
17
- error = check_result ::Libuv::Ext.prepare_start(handle, callback(:on_prepare))
18
- reject(error) if error
19
- end
20
-
21
- def stop
22
- return if @closed
23
- error = check_result ::Libuv::Ext.prepare_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_prepare(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, :prepare_cb, e
45
- end
46
- end
47
- end
48
- end
49
- end
1
+ module Libuv
2
+ class Prepare < Handle
3
+
4
+
5
+ # @param loop [::Libuv::Loop] loop this prepare handle will be associated
6
+ # @param callback [Proc] callback to be called on loop preparation
7
+ def initialize(loop, callback = nil, &blk)
8
+ @loop = loop
9
+ @callback = callback || blk
10
+
11
+ prepare_ptr = ::Libuv::Ext.create_handle(:uv_prepare)
12
+ error = check_result(::Libuv::Ext.prepare_init(@pointer, prepare_ptr))
13
+
14
+ super(prepare_ptr, error)
15
+ end
16
+
17
+ # Enables the prepare handler.
18
+ def start
19
+ return if @closed
20
+ error = check_result ::Libuv::Ext.prepare_start(handle, callback(:on_prepare))
21
+ reject(error) if error
22
+ end
23
+
24
+ # Disables the prepare handler.
25
+ def stop
26
+ return if @closed
27
+ error = check_result ::Libuv::Ext.prepare_stop(handle)
28
+ reject(error) if error
29
+ end
30
+
31
+ # Used to update the callback that will be triggered on loop prepare
32
+ #
33
+ # @param callback [Proc] the callback to be called on loop prepare
34
+ def progress(callback = nil, &blk)
35
+ @callback = callback || blk
36
+ end
37
+
38
+
39
+ private
40
+
41
+
42
+ def on_prepare(handle, status)
43
+ e = check_result(status)
44
+
45
+ if e
46
+ reject(e)
47
+ else
48
+ begin
49
+ @callback.call
50
+ rescue Exception => e
51
+ @loop.log :error, :prepare_cb, e
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
data/lib/libuv/q.rb CHANGED
@@ -382,7 +382,7 @@ module Libuv
382
382
  # @param [*Promise] Promises a number of promises that will be combined into a single promise
383
383
  # @return [Promise] Returns a single promise that will be resolved with an array of values,
384
384
  # each [result, wasResolved] value pair corresponding to a at the same index in the `promises` array.
385
- def finally(loop, *promises)
385
+ def self.finally(loop, *promises)
386
386
  deferred = Q.defer(loop)
387
387
  counter = promises.length
388
388
  results = []
@@ -0,0 +1,51 @@
1
+ module Libuv
2
+ class Signal < Handle
3
+
4
+
5
+ SIGNALS = {
6
+ :HUP => 1,
7
+ :SIGHUP => 1,
8
+ :INT => 2,
9
+ :SIGINT => 2,
10
+ :BREAK => 21,
11
+ :SIGBREAK => 21,
12
+ :WINCH => 28,
13
+ :SIGWINCH => 28
14
+ }
15
+
16
+
17
+ # @param loop [::Libuv::Loop] loop this signal handler will be associated
18
+ # @param callback [Proc] callback to be called when the signal is triggered
19
+ def initialize(loop)
20
+ @loop = loop
21
+
22
+ signal_ptr = ::Libuv::Ext.create_handle(:uv_signal)
23
+ error = check_result(::Libuv::Ext.signal_init(loop.handle, signal_ptr))
24
+
25
+ super(signal_ptr, error)
26
+ end
27
+
28
+ # Enables the signal handler.
29
+ def start(signal)
30
+ return if @closed
31
+ signal = SIGNALS[signal] if signal.is_a? Symbol
32
+ error = check_result ::Libuv::Ext.signal_start(handle, callback(:on_sig), signal)
33
+ reject(error) if error
34
+ end
35
+
36
+ # Disables the signal handler.
37
+ def stop
38
+ return if @closed
39
+ error = check_result ::Libuv::Ext.signal_stop(handle)
40
+ reject(error) if error
41
+ end
42
+
43
+
44
+ private
45
+
46
+
47
+ def on_sig(handle, signal)
48
+ defer.notify(signal) # notify of a call
49
+ end
50
+ end
51
+ end