uringmachine 0.21.0 → 0.22.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/CHANGELOG.md +14 -0
  4. data/TODO.md +144 -0
  5. data/benchmark/README.md +173 -0
  6. data/benchmark/bm_io_pipe.rb +70 -0
  7. data/benchmark/bm_io_socketpair.rb +71 -0
  8. data/benchmark/bm_mutex_cpu.rb +57 -0
  9. data/benchmark/bm_mutex_io.rb +64 -0
  10. data/benchmark/bm_pg_client.rb +109 -0
  11. data/benchmark/bm_queue.rb +76 -0
  12. data/benchmark/chart.png +0 -0
  13. data/benchmark/common.rb +135 -0
  14. data/benchmark/dns_client.rb +47 -0
  15. data/{examples/bm_http_parse.rb → benchmark/http_parse.rb} +1 -1
  16. data/benchmark/run_bm.rb +8 -0
  17. data/benchmark/sqlite.rb +108 -0
  18. data/{examples/bm_write.rb → benchmark/write.rb} +4 -4
  19. data/ext/um/um.c +189 -100
  20. data/ext/um/um.h +36 -10
  21. data/ext/um/um_async_op.c +1 -1
  22. data/ext/um/um_class.c +87 -13
  23. data/ext/um/um_op.c +6 -0
  24. data/ext/um/um_sync.c +2 -2
  25. data/ext/um/um_utils.c +16 -0
  26. data/grant-2025/journal.md +118 -1
  27. data/grant-2025/tasks.md +48 -22
  28. data/lib/uringmachine/actor.rb +8 -0
  29. data/lib/uringmachine/dns_resolver.rb +1 -2
  30. data/lib/uringmachine/fiber_scheduler.rb +127 -81
  31. data/lib/uringmachine/version.rb +1 -1
  32. data/lib/uringmachine.rb +32 -3
  33. data/test/helper.rb +7 -18
  34. data/test/test_actor.rb +12 -3
  35. data/test/test_async_op.rb +10 -10
  36. data/test/test_fiber.rb +84 -1
  37. data/test/test_fiber_scheduler.rb +950 -47
  38. data/test/test_um.rb +297 -120
  39. data/uringmachine.gemspec +2 -1
  40. metadata +38 -16
  41. data/examples/bm_fileno.rb +0 -33
  42. data/examples/bm_queue.rb +0 -111
  43. data/examples/bm_side_running.rb +0 -83
  44. data/examples/bm_sqlite.rb +0 -89
  45. data/examples/dns_client.rb +0 -12
  46. /data/{examples/bm_mutex.rb → benchmark/mutex.rb} +0 -0
  47. /data/{examples/bm_mutex_single.rb → benchmark/mutex_single.rb} +0 -0
  48. /data/{examples/bm_send.rb → benchmark/send.rb} +0 -0
  49. /data/{examples/bm_snooze.rb → benchmark/snooze.rb} +0 -0
@@ -10,7 +10,6 @@ class UringMachine
10
10
  @nameservers = get_nameservers
11
11
  @fiber = @machine.spin { handle_requests_loop }
12
12
  @last_id = 0
13
- @cache = {}
14
13
  end
15
14
 
16
15
  def resolve(hostname, type)
@@ -59,7 +58,7 @@ class UringMachine
59
58
  msg = Resolv::DNS::Message.decode buf
60
59
  addrs = []
61
60
  msg.each_answer do |name, ttl, data|
62
- p [name, ttl, data]
61
+ # p [name, ttl, data]
63
62
  if data.kind_of?(Resolv::DNS::Resource::IN::A) ||
64
63
  data.kind_of?(Resolv::DNS::Resource::IN::AAAA)
65
64
  addrs << data.address.to_s
@@ -2,31 +2,45 @@
2
2
 
3
3
  require 'resolv'
4
4
  require 'etc'
5
+ require 'uringmachine'
5
6
 
6
7
  class UringMachine
7
- # Implements a thread pool for running blocking operations.
8
+ # Implements a worker thread pool for running blocking operations. Worker
9
+ # threads are started as needed. Worker thread count is limited to the number
10
+ # of CPU cores available.
8
11
  class BlockingOperationThreadPool
12
+
13
+ # Initializes a new worker pool.
14
+ #
15
+ # @return [void]
9
16
  def initialize
10
- @blocking_op_queue = UM::Queue.new
11
17
  @pending_count = 0
12
18
  @worker_count = 0
13
19
  @max_workers = Etc.nprocessors
14
20
  @worker_mutex = UM::Mutex.new
21
+ @job_queue = UM::Queue.new
15
22
  @workers = []
16
23
  end
17
24
 
25
+ # Processes a request by submitting it to the job queue and waiting for the
26
+ # return value. Starts a worker if needed.
27
+ #
28
+ # @param machine [UringMachine] machine
29
+ # @param job [any] callable job object
30
+ # @return [any] return value
18
31
  def process(machine, job)
19
- queue = UM::Queue.new
20
-
32
+ queue = Fiber.current.mailbox
21
33
  if @worker_count == 0 || (@pending_count > 0 && @worker_count < @max_workers)
22
34
  start_worker(machine)
23
35
  end
24
- machine.push(@blocking_op_queue, [queue, job])
36
+ machine.push(@job_queue, [queue, job])
25
37
  machine.shift(queue)
26
38
  end
27
39
 
28
40
  private
29
41
 
42
+ # @param machine [UringMachine] machine
43
+ # @return [void]
30
44
  def start_worker(machine)
31
45
  machine.synchronize(@worker_mutex) do
32
46
  return if @worker_count == @max_workers
@@ -36,10 +50,11 @@ class UringMachine
36
50
  end
37
51
  end
38
52
 
53
+ # @return [void]
39
54
  def run_worker_thread
40
- machine = UM.new(4).mark(1)
55
+ machine = UM.new(4)
41
56
  loop do
42
- q, op = machine.shift(@blocking_op_queue)
57
+ q, op = machine.shift(@job_queue)
43
58
  @pending_count += 1
44
59
  res = begin
45
60
  op.()
@@ -50,6 +65,7 @@ class UringMachine
50
65
  machine.push(q, res)
51
66
  rescue => e
52
67
  UM.debug("worker e: #{e.inspect}")
68
+ exit!
53
69
  end
54
70
  end
55
71
  end
@@ -58,9 +74,15 @@ class UringMachine
58
74
  # creating fiber-based concurrent applications in Ruby, in tight integration
59
75
  # with the standard Ruby I/O and locking APIs.
60
76
  class FiberScheduler
77
+
78
+ # The blocking operation thread pool is shared by all fiber schedulers.
61
79
  @@blocking_operation_thread_pool = BlockingOperationThreadPool.new
62
80
 
63
- attr_reader :machine, :fiber_map
81
+ # UringMachine instance associated with scheduler.
82
+ attr_reader :machine
83
+
84
+ # WeakMap holding references scheduler fibers as keys.
85
+ attr_reader :fiber_map
64
86
 
65
87
  # Instantiates a scheduler with the given UringMachine instance.
66
88
  #
@@ -73,40 +95,36 @@ class UringMachine
73
95
  def initialize(machine = nil)
74
96
  @machine = machine || UM.new
75
97
  @fiber_map = ObjectSpace::WeakMap.new
98
+ @thread = Thread.current
76
99
  end
77
100
 
101
+ # :nodoc:
78
102
  def instance_variables_to_inspect
79
103
  [:@machine]
80
104
  end
81
105
 
82
- # Should be called after a fork (eventually, we'll want Ruby to call this
83
- # automatically after a fork).
106
+ # Creates a new fiber with the given block. The created fiber is added to
107
+ # the fiber map, scheduled on the scheduler machine, and started before this
108
+ # method returns (by calling snooze).
84
109
  #
85
- # @return [self]
86
- def process_fork
87
- @machine = UM.new
88
- @fiber_map = ObjectSpace::WeakMap.new
89
- self
90
- end
110
+ # @param block [Proc] fiber block @return [Fiber]
111
+ def fiber(&block)
112
+ fiber = Fiber.new(blocking: false) { @machine.run(fiber, &block) }
91
113
 
92
- # For debugging purposes
93
- def method_missing(sym, *a, **b)
94
- @machine.write(1, "method_missing: #{sym.inspect} #{a.inspect} #{b.inspect}\n")
95
- @machine.write(1, "#{caller.inspect}\n")
96
- super
114
+ @fiber_map[fiber] = true
115
+ @machine.schedule(fiber, nil)
116
+ @machine.snooze
117
+ fiber
97
118
  end
98
119
 
99
- # scheduler_close hook: Waits for all fiber to terminate. Called upon thread
100
- # termination or when the thread's fiber scheduler is changed.
120
+ # Waits for all fiber to terminate. Called upon thread termination or when
121
+ # the thread's fiber scheduler is changed.
101
122
  #
102
123
  # @return [void]
103
124
  def scheduler_close
104
125
  join()
105
126
  end
106
127
 
107
- # For debugging purposes
108
- def p(o) = UM.debug(o.inspect)
109
-
110
128
  # Waits for the given fibers to terminate. If no fibers are given, waits for
111
129
  # all fibers to terminate.
112
130
  #
@@ -118,49 +136,36 @@ class UringMachine
118
136
  @fiber_map = ObjectSpace::WeakMap.new
119
137
  end
120
138
 
121
- @machine.join(*fibers)
139
+ @machine.await_fibers(fibers)
122
140
  end
123
141
 
124
- # blocking_operation_wait hook: runs the given operation in a separate
125
- # thread, so as not to block other fibers.
142
+ # Runs the given operation in a separate thread, so as not to block other
143
+ # fibers.
126
144
  #
127
- # @param blocking_operation [callable] blocking operation
145
+ # @param op [callable] blocking operation
128
146
  # @return [void]
129
- def blocking_operation_wait(blocking_operation)
130
- # naive_blocking_peration_wait(blocking_operation)
131
- @@blocking_operation_thread_pool.process(@machine, blocking_operation)
132
- end
133
-
134
- def naive_blocking_peration_wait(blocking_operation)
135
- res = nil
136
- Thread.new do
137
- res = blocking_operation.()
138
- rescue => e
139
- res = e
140
- end.join
141
- res
147
+ def blocking_operation_wait(op)
148
+ @@blocking_operation_thread_pool.process(@machine, op)
142
149
  end
143
150
 
144
- # block hook: blocks the current fiber by yielding to the machine. This hook
145
- # is called when a synchronization mechanism blocks, e.g. a mutex, a queue,
146
- # etc.
151
+ # Blocks the current fiber by yielding to the machine. This hook is called
152
+ # when a synchronization mechanism blocks, e.g. a mutex, a queue, etc.
147
153
  #
148
154
  # @param blocker [any] blocker object
149
- # @param timeout [Number, nil] optional
150
- # timeout @return [bool] was the operation successful
155
+ # @param timeout [Number, nil] optional timeout
156
+ # @return [bool] was the operation successful
151
157
  def block(blocker, timeout = nil)
152
158
  if timeout
153
159
  @machine.timeout(timeout, Timeout::Error) { @machine.yield }
154
160
  else
155
161
  @machine.yield
156
162
  end
157
-
158
163
  true
159
164
  rescue Timeout::Error
160
165
  false
161
166
  end
162
167
 
163
- # unblock hook: unblocks the given fiber by scheduling it. This hook is
168
+ # Unblocks the given fiber by scheduling it. This hook is
164
169
  # called when a synchronization mechanism unblocks, e.g. a mutex, a queue,
165
170
  # etc.
166
171
  #
@@ -169,28 +174,31 @@ class UringMachine
169
174
  # @return [void]
170
175
  def unblock(blocker, fiber)
171
176
  @machine.schedule(fiber, nil)
172
- @machine.wakeup
177
+ @machine.wakeup if Thread.current != @thread
173
178
  end
174
179
 
175
- # kernel_sleep hook: sleeps for the given duration.
180
+ # Sleeps for the given duration.
176
181
  #
177
182
  # @param duration [Number, nil] sleep duration
178
183
  # @return [void]
179
184
  def kernel_sleep(duration = nil)
180
- if duration
181
- @machine.sleep(duration)
182
- else
183
- @machine.yield
184
- end
185
+ duration ? @machine.sleep(duration) : @machine.yield
185
186
  end
186
187
 
187
- # io_wait hook: waits for the given io to become ready.
188
+ # Yields to the next runnable fiber.
189
+ def yield
190
+ @machine.snooze
191
+ # @machine.yield
192
+ end
193
+
194
+ # Waits for the given io to become ready.
188
195
  #
189
196
  # @param io [IO] IO object
190
197
  # @param events [Number] readiness bitmask
191
198
  # @param timeout [Number, nil] optional timeout
192
199
  # @param return
193
200
  def io_wait(io, events, timeout = nil)
201
+ # p(io_wait: io, events:)
194
202
  timeout ||= io.timeout
195
203
  if timeout
196
204
  @machine.timeout(timeout, Timeout::Error) {
@@ -201,10 +209,16 @@ class UringMachine
201
209
  end
202
210
  end
203
211
 
212
+ # Selects the first ready IOs from the given sets of IOs.
213
+ #
214
+ # @param rios [Array<IO>] readable IOs
215
+ # @param wios [Array<IO>] writable IOs
216
+ # @param eios [Array<IO>] exceptable IOs
217
+ # @param timeout [Number, nil] optional timeout
204
218
  def io_select(rios, wios, eios, timeout = nil)
205
- map_r = map_io_fds(rios)
206
- map_w = map_io_fds(wios)
207
- map_e = map_io_fds(eios)
219
+ map_r = map_fds(rios)
220
+ map_w = map_fds(wios)
221
+ map_e = map_fds(eios)
208
222
 
209
223
  r, w, e = nil
210
224
  if timeout
@@ -218,20 +232,7 @@ class UringMachine
218
232
  [unmap_fds(r, map_r), unmap_fds(w, map_w), unmap_fds(e, map_e)]
219
233
  end
220
234
 
221
- # fiber hook: creates a new fiber with the given block. The created fiber is
222
- # added to the fiber map, scheduled on the scheduler machine, and started
223
- # before this method returns (by calling snooze).
224
- #
225
- # @param block [Proc] fiber block @return [Fiber]
226
- def fiber(&block)
227
- fiber = Fiber.new(blocking: false) { @machine.run(fiber, &block) }
228
- @fiber_map[fiber] = true
229
- @machine.schedule(fiber, nil)
230
- @machine.snooze
231
- fiber
232
- end
233
-
234
- # io_read hook: reads from the given IO.
235
+ # Reads from the given IO.
235
236
  #
236
237
  # @param io [IO] IO object
237
238
  # @param buffer [IO::Buffer] read buffer
@@ -254,7 +255,7 @@ class UringMachine
254
255
  retry
255
256
  end
256
257
 
257
- # io_pread hook: reads from the given IO at the given offset
258
+ # Reads from the given IO at the given file offset
258
259
  #
259
260
  # @param io [IO] IO object
260
261
  # @param buffer [IO::Buffer] read buffer
@@ -278,7 +279,7 @@ class UringMachine
278
279
  retry
279
280
  end
280
281
 
281
- # io_write hook: writes to the given IO.
282
+ # Writes to the given IO.
282
283
  #
283
284
  # @param io [IO] IO object
284
285
  # @param buffer [IO::Buffer] write buffer
@@ -303,7 +304,7 @@ class UringMachine
303
304
  retry
304
305
  end
305
306
 
306
- # io_pwrite hook: writes to the given IO at the given offset.
307
+ # Writes to the given IO at the given file offset.
307
308
  #
308
309
  # @param io [IO] IO object
309
310
  # @param buffer [IO::Buffer] write buffer
@@ -329,35 +330,80 @@ class UringMachine
329
330
  retry
330
331
  end
331
332
 
333
+ # Closes the given fd.
334
+ #
335
+ # @param fd [Integer] file descriptor
336
+ # @return [Integer] file descriptor
337
+ def io_close(fd)
338
+ # p(io_close: fd)
339
+ @machine.close_async(fd)
340
+ end
341
+
332
342
  if UM.method_defined?(:waitid_status)
343
+
344
+ # Waits for a process to terminate.
345
+ #
346
+ # @param pid [Integer] process pid (0 for any child process)
347
+ # @param flags [Integer] waitpid flags
348
+ # @return [Process::Status] terminated process status
333
349
  def process_wait(pid, flags)
334
350
  flags = UM::WEXITED if flags == 0
335
351
  @machine.waitid_status(UM::P_PID, pid, flags)
336
352
  end
337
353
  end
338
354
 
355
+ # Interrupts the given fiber with an exception.
356
+ #
357
+ # @param fiber [Fiber] fiber to interrupt
358
+ # @param exception [Exception] Exception
359
+ # @return [void]
339
360
  def fiber_interrupt(fiber, exception)
340
361
  @machine.schedule(fiber, exception)
341
362
  @machine.wakeup
342
363
  end
343
364
 
365
+ # Resolves an hostname.
366
+ #
367
+ # @param hostname [String] hostname to resolve
368
+ # @return [Array<Addrinfo>] array of resolved addresses
344
369
  def address_resolve(hostname)
345
370
  Resolv.getaddresses(hostname)
346
371
  end
347
372
 
373
+ # Run the given block with a timeout.
374
+ #
375
+ # @param duration [Number] timeout duration
376
+ # @param exception [Class] exception Class
377
+ # @param message [String] exception message
378
+ # @param block [Proc] block to run
379
+ # @return [any] block return value
348
380
  def timeout_after(duration, exception, message, &block)
349
381
  @machine.timeout(duration, exception, &block)
350
382
  end
351
383
 
352
384
  private
353
385
 
354
- def map_io_fds(ios)
386
+ # Prints the given object for debugging purposes.
387
+ #
388
+ # @param o [any]
389
+ # @return [void]
390
+ def p(o) = UM.debug(o.inspect)
391
+
392
+ # Maps the given ios to fds.
393
+ #
394
+ # @param ios [Array<IO>] IOs to map
395
+ # @return [Hash] hash mapping fds to IOs
396
+ def map_fds(ios)
355
397
  ios.each_with_object({}) { |io, h| h[io.fileno] = io }
356
398
  end
357
399
 
400
+ # Maps the given fds to IOs using the given fd-to-IO map.
401
+ #
402
+ # @param fds [Array<Integer>] fds to map
403
+ # @param map [Hash] hash mapping fds to IOs
404
+ # @return [Array<IO>] IOs corresponding to fds
358
405
  def unmap_fds(fds, map)
359
406
  fds.map { map[it] }
360
407
  end
361
-
362
408
  end
363
- end
409
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UringMachine
4
- VERSION = '0.21.0'
4
+ VERSION = '0.22.0'
5
5
  end
data/lib/uringmachine.rb CHANGED
@@ -38,7 +38,7 @@ class UringMachine
38
38
  results[f] = f.result
39
39
  else
40
40
  (pending ||= []) << f
41
- queue ||= UM::Queue.new
41
+ queue ||= Fiber.current.mailbox
42
42
  f.add_done_listener(queue)
43
43
  end
44
44
  end
@@ -53,6 +53,35 @@ class UringMachine
53
53
  fibers.size == 1 ? values.first : values
54
54
  end
55
55
 
56
+ def await_fibers(fibers)
57
+ if fibers.is_a?(Fiber)
58
+ f = fibers
59
+ if !f.done?
60
+ queue = Fiber.current.mailbox
61
+ f.add_done_listener(queue)
62
+ self.shift(queue)
63
+ end
64
+ return 1
65
+ end
66
+
67
+ queue = nil
68
+ pending = nil
69
+ fibers.each do |f|
70
+ if !f.done?
71
+ (pending ||= []) << f
72
+ queue ||= Fiber.current.mailbox
73
+ f.add_done_listener(queue)
74
+ end
75
+ end
76
+ if pending
77
+ while !pending.empty?
78
+ f = self.shift(queue)
79
+ pending.delete(f)
80
+ end
81
+ end
82
+ fibers.count
83
+ end
84
+
56
85
  def resolve(hostname, type = :A)
57
86
  @resolver ||= DNSResolver.new(self)
58
87
  @resolver.resolve(hostname, type)
@@ -71,8 +100,8 @@ class UringMachine
71
100
  @@fiber_map.delete(fiber)
72
101
  self.notify_done_listeners(fiber)
73
102
 
74
- # transfer control to UM scheduler
75
- self.yield
103
+ # switch away to a different fiber
104
+ self.switch
76
105
  end
77
106
 
78
107
  def notify_done_listeners(fiber)
data/test/helper.rb CHANGED
@@ -5,6 +5,7 @@ require_relative './coverage' if ENV['COVERAGE']
5
5
  require 'uringmachine'
6
6
  require 'socket'
7
7
  require 'minitest/autorun'
8
+ require 'securerandom'
8
9
 
9
10
  STDOUT.sync = true
10
11
  STDERR.sync = true
@@ -64,30 +65,18 @@ class UMBaseTest < Minitest::Test
64
65
  end
65
66
 
66
67
  def teardown
67
- # @machine&.cleanup
68
+ pending_fibers = @machine.pending_fibers.keys
69
+ if pending_fibers.size > 0
70
+ raise "leaked fibers: #{pending_fibers}"
71
+ end
72
+ GC.start
68
73
  end
69
74
 
70
75
  def assign_port
71
76
  @@port_assign_mutex ||= Mutex.new
72
77
  @@port_assign_mutex.synchronize do
73
- @@port ||= 1024 + rand(60000)
78
+ @@port ||= 1024 + SecureRandom.rand(60000)
74
79
  @@port += 1
75
80
  end
76
81
  end
77
-
78
- def make_socket_pair
79
- port = 10000 + rand(30000)
80
- server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
81
- @machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
82
- @machine.bind(server_fd, '127.0.0.1', port)
83
- @machine.listen(server_fd, UM::SOMAXCONN)
84
-
85
- client_conn_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
86
- @machine.connect(client_conn_fd, '127.0.0.1', port)
87
-
88
- server_conn_fd = @machine.accept(server_fd)
89
-
90
- @machine.close(server_fd)
91
- [client_conn_fd, server_conn_fd]
92
- end
93
82
  end
data/test/test_actor.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
- require 'socket'
5
4
  require 'uringmachine/actor'
6
5
 
7
6
  class ActorTest < UMBaseTest
@@ -25,7 +24,7 @@ class ActorTest < UMBaseTest
25
24
 
26
25
  def test_basic_actor_functionality
27
26
  mailbox = UM::Queue.new
28
- actor = @machine.spin_actor(Counter)
27
+ actor = machine.spin_actor(Counter)
29
28
 
30
29
  assert_kind_of Fiber, actor
31
30
 
@@ -35,6 +34,11 @@ class ActorTest < UMBaseTest
35
34
  assert_equal 2, actor.call(mailbox, :get)
36
35
  assert_equal actor, actor.cast(:reset)
37
36
  assert_equal 0, actor.call(mailbox, :get)
37
+ ensure
38
+ if actor
39
+ actor.stop
40
+ machine.join(actor)
41
+ end
38
42
  end
39
43
 
40
44
  module Counter2
@@ -56,10 +60,15 @@ class ActorTest < UMBaseTest
56
60
  end
57
61
 
58
62
 
59
- def test_actor_with_args
63
+ def test_spin_actor_with_args
60
64
  actor = @machine.spin_actor(Counter2, 43)
61
65
  mailbox = UM::Queue.new
62
66
 
63
67
  assert_equal 43, actor.call(mailbox, :get)
68
+ ensure
69
+ if actor
70
+ actor.stop
71
+ machine.join(actor)
72
+ end
64
73
  end
65
74
  end
@@ -11,22 +11,22 @@ class AsyncOpTest < UMBaseTest
11
11
  end
12
12
 
13
13
  def test_async_op_await
14
- assert_equal 1, machine.pending_count
14
+ assert_equal 1, machine.metrics[:ops_pending]
15
15
  res = @op.await
16
16
  t1 = monotonic_clock
17
17
  assert_in_range 0.04..0.08, t1 - @t0
18
- assert_equal 0, machine.pending_count
18
+ assert_equal 0, machine.metrics[:ops_pending]
19
19
  assert_equal (-ETIME), res
20
20
  assert_equal true, @op.done?
21
21
  assert_equal false, @op.cancelled?
22
22
  end
23
23
 
24
24
  def test_async_op_join
25
- assert_equal 1, machine.pending_count
25
+ assert_equal 1, machine.metrics[:ops_pending]
26
26
  res = @op.join
27
27
  t1 = monotonic_clock
28
28
  assert_in_range 0.04..0.08, t1 - @t0
29
- assert_equal 0, machine.pending_count
29
+ assert_equal 0, machine.metrics[:ops_pending]
30
30
  assert_equal (-ETIME), res
31
31
  assert_equal true, @op.done?
32
32
  assert_equal false, @op.cancelled?
@@ -34,13 +34,13 @@ class AsyncOpTest < UMBaseTest
34
34
 
35
35
  def test_async_op_cancel
36
36
  machine.sleep(0.01)
37
- assert_equal 1, machine.pending_count
37
+ assert_equal 1, machine.metrics[:ops_pending]
38
38
  @op.cancel
39
39
  assert_equal false, @op.done?
40
40
 
41
41
  machine.sleep(0.01)
42
42
 
43
- assert_equal 0, machine.pending_count
43
+ assert_equal 0, machine.metrics[:ops_pending]
44
44
  assert_equal true, @op.done?
45
45
  assert_equal (-ECANCELED), @op.result
46
46
  assert_equal true, @op.cancelled?
@@ -53,7 +53,7 @@ class AsyncOpTest < UMBaseTest
53
53
 
54
54
  res = @op.await
55
55
 
56
- assert_equal 0, machine.pending_count
56
+ assert_equal 0, machine.metrics[:ops_pending]
57
57
  assert_equal true, @op.done?
58
58
  assert_equal (-ECANCELED), res
59
59
  assert_equal true, @op.cancelled?
@@ -71,7 +71,7 @@ class AsyncOpTest < UMBaseTest
71
71
  rescue => e
72
72
  end
73
73
 
74
- assert_equal 0, machine.pending_count
74
+ assert_equal 0, machine.metrics[:ops_pending]
75
75
  assert_kind_of TOError, e
76
76
  assert_equal true, @op.done?
77
77
  assert_equal (-ECANCELED), @op.result
@@ -89,7 +89,7 @@ class AsyncOpTest < UMBaseTest
89
89
  end
90
90
 
91
91
  # machine.timeout is cancelled async, so CQE is not yet reaped
92
- assert_equal 1, machine.pending_count
92
+ assert_equal 1, machine.metrics[:ops_pending]
93
93
  assert_nil e
94
94
  assert_equal true, @op.done?
95
95
  assert_equal (-ETIME), @op.result
@@ -97,7 +97,7 @@ class AsyncOpTest < UMBaseTest
97
97
 
98
98
  # wait for timeout cancellation
99
99
  machine.sleep(0.01)
100
- assert_equal 0, machine.pending_count
100
+ assert_equal 0, machine.metrics[:ops_pending]
101
101
  end
102
102
  end
103
103