libuv 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE +24 -0
  8. data/README.md +73 -0
  9. data/Rakefile +31 -0
  10. data/lib/libuv.rb +34 -0
  11. data/lib/libuv/assertions.rb +23 -0
  12. data/lib/libuv/async.rb +33 -0
  13. data/lib/libuv/check.rb +49 -0
  14. data/lib/libuv/error.rb +70 -0
  15. data/lib/libuv/ext/ext.rb +257 -0
  16. data/lib/libuv/ext/platform/darwin_x64.rb +12 -0
  17. data/lib/libuv/ext/platform/linux.rb +8 -0
  18. data/lib/libuv/ext/platform/unix.rb +14 -0
  19. data/lib/libuv/ext/platform/windows.rb +27 -0
  20. data/lib/libuv/ext/tasks.rb +27 -0
  21. data/lib/libuv/ext/tasks/mac.rb +23 -0
  22. data/lib/libuv/ext/tasks/unix.rb +23 -0
  23. data/lib/libuv/ext/tasks/win.rb +11 -0
  24. data/lib/libuv/ext/types.rb +230 -0
  25. data/lib/libuv/fs_event.rb +31 -0
  26. data/lib/libuv/handle.rb +82 -0
  27. data/lib/libuv/idle.rb +49 -0
  28. data/lib/libuv/listener.rb +34 -0
  29. data/lib/libuv/loop.rb +310 -0
  30. data/lib/libuv/net.rb +38 -0
  31. data/lib/libuv/pipe.rb +97 -0
  32. data/lib/libuv/prepare.rb +49 -0
  33. data/lib/libuv/q.rb +429 -0
  34. data/lib/libuv/resource.rb +28 -0
  35. data/lib/libuv/simple_async.rb +28 -0
  36. data/lib/libuv/stream.rb +124 -0
  37. data/lib/libuv/tcp.rb +194 -0
  38. data/lib/libuv/timer.rb +75 -0
  39. data/lib/libuv/tty.rb +34 -0
  40. data/lib/libuv/udp.rb +256 -0
  41. data/lib/libuv/version.rb +3 -0
  42. data/lib/libuv/work.rb +62 -0
  43. data/libuv.gemspec +54 -0
  44. data/spec/async_spec.rb +60 -0
  45. data/spec/defer_spec.rb +980 -0
  46. data/spec/idle_spec.rb +56 -0
  47. data/spec/pipe_spec.rb +148 -0
  48. data/spec/tcp_spec.rb +188 -0
  49. metadata +382 -0
@@ -0,0 +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
28
+ end
@@ -0,0 +1,28 @@
1
+ module Libuv
2
+ class SimpleAsync < Async
3
+
4
+
5
+ def initialize(loop, callback = nil, &blk)
6
+ @callback = callback || blk
7
+ super(loop)
8
+ end
9
+
10
+
11
+ private
12
+
13
+
14
+ def on_async(handle, status)
15
+ e = check_result(status)
16
+
17
+ if e
18
+ reject(e)
19
+ else
20
+ begin
21
+ @callback.call
22
+ rescue Exception => e
23
+ @loop.log :error, :simple_async_cb, e
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,124 @@
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
+ def listen(backlog)
10
+ return if @closed
11
+ assert_type(Integer, backlog, BACKLOG_ERROR)
12
+ error = check_result ::Libuv::Ext.listen(handle, Integer(backlog), callback(:on_listen))
13
+ reject(error) if error
14
+ end
15
+
16
+ # Starts reading from the handle
17
+ def start_read
18
+ error = check_result ::Libuv::Ext.read_start(handle, callback(:on_allocate), callback(:on_read))
19
+ reject(error) if error
20
+ end
21
+
22
+ # Stops reading from the handle
23
+ def stop_read
24
+ error = check_result ::Libuv::Ext.read_stop(handle)
25
+ reject(error) if error
26
+ end
27
+
28
+ # Shutsdown the writes on the handle waiting until the last write is complete before triggering the callback
29
+ def shutdown
30
+ error = check_result ::Libuv::Ext.shutdown(::Libuv::Ext.create_request(:uv_shutdown), handle, callback(:on_shutdown))
31
+ reject(error) if error
32
+ end
33
+
34
+ def write(data)
35
+ deferred = @loop.defer
36
+ begin
37
+ assert_type(String, data, WRITE_ERROR)
38
+
39
+ size = data.respond_to?(:bytesize) ? data.bytesize : data.size
40
+ buffer = ::Libuv::Ext.buf_init(FFI::MemoryPointer.from_string(data), size)
41
+
42
+ # local as this variable will be avaliable until the handle is closed
43
+ @write_callbacks = @write_callbacks || []
44
+
45
+ #
46
+ # create the curried callback
47
+ #
48
+ callback = FFI::Function.new(:void, [:pointer, :int]) do |req, status|
49
+ ::Libuv::Ext.free(req)
50
+ # remove the callback from the array
51
+ # assumes writes are done in order
52
+ promise = @write_callbacks.shift[0]
53
+ resolve promise, status
54
+ end
55
+
56
+
57
+ @write_callbacks << [deferred, callback]
58
+ req = ::Libuv::Ext.create_request(:uv_write)
59
+ error = check_result ::Libuv::Ext.write(req, handle, buffer, 1, callback)
60
+
61
+ if error
62
+ @write_callbacks.pop
63
+ ::Libuv::Ext.free(req)
64
+ deferred.reject(error)
65
+
66
+ reject(error) # close the handle
67
+ end
68
+ rescue Exception => e
69
+ deferred.reject(e) # this write exception may not be fatal
70
+ end
71
+ deferred.promise
72
+ end
73
+
74
+ def readable?
75
+ ::Libuv::Ext.is_readable(handle) > 0
76
+ end
77
+
78
+ def writable?
79
+ ::Libuv::Ext.is_writable(handle) > 0
80
+ end
81
+
82
+
83
+ private
84
+
85
+
86
+ def on_listen(server, status)
87
+ e = check_result(status)
88
+
89
+ if e
90
+ reject(e) # is this cause for closing the handle?
91
+ else
92
+ begin
93
+ @on_listen.call(self)
94
+ rescue Exception => e
95
+ @loop.log :error, :stream_listen_cb, e
96
+ end
97
+ end
98
+ end
99
+
100
+ def on_allocate(client, suggested_size)
101
+ ::Libuv::Ext.buf_init(::Libuv::Ext.malloc(suggested_size), suggested_size)
102
+ end
103
+
104
+ def on_read(handle, nread, buf)
105
+ e = check_result(nread)
106
+ base = buf[:base]
107
+
108
+ if e
109
+ ::Libuv::Ext.free(base)
110
+ reject(e)
111
+ else
112
+ data = base.read_string(nread)
113
+ ::Libuv::Ext.free(base)
114
+ defer.notify(data) # stream the data
115
+ end
116
+ end
117
+
118
+ def on_shutdown(req, status)
119
+ ::Libuv::Ext.free(req)
120
+ @close_error = check_result(status)
121
+ close
122
+ end
123
+ end
124
+ end
data/lib/libuv/tcp.rb ADDED
@@ -0,0 +1,194 @@
1
+ require 'ipaddr'
2
+
3
+
4
+ module Libuv
5
+ class TCP < Handle
6
+ include Stream, Net
7
+
8
+
9
+ KEEPALIVE_ARGUMENT_ERROR = "delay must be an Integer".freeze
10
+
11
+
12
+ def initialize(loop, acceptor = nil)
13
+ @loop = loop
14
+
15
+ tcp_ptr = ::Libuv::Ext.create_handle(:uv_tcp)
16
+ error = check_result(::Libuv::Ext.tcp_init(loop.handle, tcp_ptr))
17
+ error = check_result(::Libuv::Ext.accept(acceptor, tcp_ptr)) if acceptor && error.nil?
18
+
19
+ super(tcp_ptr, error)
20
+ end
21
+
22
+ def bind(ip, port, callback = nil, &blk)
23
+ @on_listen = callback || blk
24
+ assert_type(String, ip, IP_ARGUMENT_ERROR)
25
+ assert_type(Integer, port, PORT_ARGUMENT_ERROR)
26
+
27
+ begin
28
+ @tcp_socket = create_socket(IPAddr.new(ip), port)
29
+ @tcp_socket.bind
30
+ rescue Exception => e
31
+ reject(e)
32
+ end
33
+ end
34
+
35
+ def accept(callback = nil, &blk)
36
+ tcp = nil
37
+ begin
38
+ tcp = TCP.new(loop, handle)
39
+ rescue Exception => e
40
+ @loop.log :info, :tcp_accept_failed, e
41
+ end
42
+ if tcp
43
+ begin
44
+ (callback || blk).call(tcp)
45
+ rescue Exception => e
46
+ @loop.log :error, :tcp_accept_cb, e
47
+ end
48
+ end
49
+ nil
50
+ end
51
+
52
+ def connect(ip, port, callback = nil, &blk)
53
+ @callback = callback || blk
54
+ assert_type(String, ip, IP_ARGUMENT_ERROR)
55
+ assert_type(Integer, port, PORT_ARGUMENT_ERROR)
56
+
57
+ begin
58
+ @tcp_socket = create_socket(IPAddr.new(ip), port)
59
+ @tcp_socket.connect(callback(:on_connect))
60
+ rescue Exception => e
61
+ reject(e)
62
+ end
63
+ end
64
+
65
+ def sockname
66
+ sockaddr, len = get_sockaddr_and_len
67
+ check_result! ::Libuv::Ext.tcp_getsockname(handle, sockaddr, len)
68
+ get_ip_and_port(::Libuv::Sockaddr.new(sockaddr), len.get_int(0))
69
+ end
70
+
71
+ def peername
72
+ sockaddr, len = get_sockaddr_and_len
73
+ check_result! ::Libuv::Ext.tcp_getpeername(handle, sockaddr, len)
74
+ get_ip_and_port(::Libuv::Sockaddr.new(sockaddr), len.get_int(0))
75
+ end
76
+
77
+ def enable_nodelay
78
+ check_result ::Libuv::Ext.tcp_nodelay(handle, 1)
79
+ end
80
+
81
+ def disable_nodelay
82
+ check_result ::Libuv::Ext.tcp_nodelay(handle, 0)
83
+ end
84
+
85
+ def enable_keepalive(delay)
86
+ assert_type(Integer, delay, KEEPALIVE_ARGUMENT_ERROR)
87
+ check_result ::Libuv::Ext.tcp_keepalive(handle, 1, delay)
88
+ end
89
+
90
+ def disable_keepalive
91
+ check_result ::Libuv::Ext.tcp_keepalive(handle, 0, 0)
92
+ end
93
+
94
+ def enable_simultaneous_accepts
95
+ check_result ::Libuv::Ext.tcp_simultaneous_accepts(handle, 1)
96
+ end
97
+
98
+ def disable_simultaneous_accepts
99
+ check_result ::Libuv::Ext.tcp_simultaneous_accepts(handle, 0)
100
+ end
101
+
102
+
103
+ private
104
+
105
+
106
+ def create_socket(ip, port)
107
+ if ip.ipv4?
108
+ Socket4.new(loop, handle, ip.to_s, port)
109
+ else
110
+ Socket6.new(loop, handle, ip.to_s, port)
111
+ end
112
+ end
113
+
114
+ def on_connect(req, status)
115
+ ::Libuv::Ext.free(req)
116
+ @callback.call(self)
117
+ end
118
+
119
+
120
+ class SocketBase
121
+ include Resource
122
+
123
+ def initialize(loop, tcp, ip, port)
124
+ @tcp, @sockaddr = tcp, ip_addr(ip, port)
125
+ end
126
+
127
+ def bind
128
+ check_result!(tcp_bind)
129
+ end
130
+
131
+ def connect(callback)
132
+ check_result!(tcp_connect(callback))
133
+ end
134
+
135
+
136
+ private
137
+
138
+
139
+ def connect_req
140
+ ::Libuv::Ext.create_request(:uv_connect)
141
+ end
142
+ end
143
+
144
+
145
+ class Socket4 < SocketBase
146
+
147
+
148
+ private
149
+
150
+
151
+ def ip_addr(ip, port)
152
+ ::Libuv::Ext.ip4_addr(ip, port)
153
+ end
154
+
155
+ def tcp_bind
156
+ ::Libuv::Ext.tcp_bind(@tcp, @sockaddr)
157
+ end
158
+
159
+ def tcp_connect(callback)
160
+ ::Libuv::Ext.tcp_connect(
161
+ connect_req,
162
+ @tcp,
163
+ @sockaddr,
164
+ callback
165
+ )
166
+ end
167
+ end
168
+
169
+
170
+ class Socket6 < SocketBase
171
+
172
+
173
+ private
174
+
175
+
176
+ def ip_addr(ip, port)
177
+ ::Libuv::Ext.ip6_addr(ip, port)
178
+ end
179
+
180
+ def tcp_bind
181
+ ::Libuv::Ext.tcp_bind6(@tcp, @sockaddr)
182
+ end
183
+
184
+ def tcp_connect(callback)
185
+ ::Libuv::Ext.tcp_connect6(
186
+ connect_req,
187
+ @tcp,
188
+ @sockaddr,
189
+ callback
190
+ )
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,75 @@
1
+ module Libuv
2
+ class Timer < Handle
3
+ include Assertions
4
+
5
+
6
+ TIMEOUT_ERROR = "timeout must be an Integer".freeze
7
+ REPEAT_ERROR = "repeat must be an Integer".freeze
8
+
9
+
10
+ def initialize(loop, callback = nil)
11
+ @loop, @callback = loop, callback
12
+
13
+ timer_ptr = ::Libuv::Ext.create_handle(:uv_timer)
14
+ error = check_result(::Libuv::Ext.timer_init(loop.handle, timer_ptr))
15
+
16
+ super(timer_ptr, error)
17
+ end
18
+
19
+ def start(timeout, repeat = 0)
20
+ return if @closed
21
+
22
+ assert_type(Integer, timeout, TIMEOUT_ERROR)
23
+ assert_type(Integer, repeat, REPEAT_ERROR)
24
+
25
+ error = check_result ::Libuv::Ext.timer_start(handle, callback(:on_timer), timeout, repeat)
26
+ reject(error) if error
27
+ end
28
+
29
+ def stop
30
+ return if @closed
31
+ error = check_result ::Libuv::Ext.timer_stop(handle)
32
+ reject(error) if error
33
+ end
34
+
35
+ def again
36
+ return if @closed
37
+ error = check_result ::Libuv::Ext.timer_again(handle)
38
+ reject(error) if error
39
+ end
40
+
41
+ def repeat=(repeat)
42
+ return if @closed
43
+ assert_type(Integer, repeat, REPEAT_ERROR)
44
+ check_result ::Libuv::Ext.timer_set_repeat(handle, repeat)
45
+ reject(error) if error
46
+ end
47
+
48
+ def repeat
49
+ return if @closed
50
+ ::Libuv::Ext.timer_get_repeat(handle)
51
+ end
52
+
53
+ def progress(callback = nil, &blk)
54
+ @callback = callback || blk
55
+ end
56
+
57
+
58
+ private
59
+
60
+
61
+ def on_timer(handle, status)
62
+ e = check_result(status)
63
+
64
+ if e
65
+ reject(e)
66
+ else
67
+ begin
68
+ @callback.call
69
+ rescue Exception => e
70
+ @loop.log :error, :timer_cb, e
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end