Skip to content

Commit ffc19a4

Browse files
committed
Add missing documentation and improve documentation consistency.
1 parent 0b4930d commit ffc19a4

12 files changed

+124
-37
lines changed

lib/async/barrier.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
module Async
1010
# A general purpose synchronisation primitive, which allows one task to wait for a number of other tasks to complete. It can be used in conjunction with {Semaphore}.
1111
#
12-
# @public Since `stable-v1`.
12+
# @public Since *Async v1*.
1313
class Barrier
1414
# Initialize the barrier.
1515
# @parameter parent [Task | Semaphore | Nil] The parent for holding any children tasks.
16-
# @public Since `stable-v1`.
16+
# @public Since *Async v1*.
1717
def initialize(parent: nil)
1818
@tasks = List.new
1919

lib/async/clock.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
module Async
77
# A convenient wrapper around the internal monotonic clock.
8-
# @public Since `stable-v1`.
8+
# @public Since *Async v1*.
99
class Clock
1010
# Get the current elapsed monotonic time.
1111
def self.now

lib/async/condition.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
module Async
1111
# A synchronization primitive, which allows fibers to wait until a particular condition is (edge) triggered.
12-
# @public Since `stable-v1`.
12+
# @public Since *Async v1*.
1313
class Condition
1414
# Create a new condition.
1515
def initialize

lib/async/console.rb

+5
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ module Async
1212
#
1313
# This is an experimental feature.
1414
module Console
15+
# Log a message at the debug level. The shim is silent.
1516
def self.debug(...)
1617
end
1718

19+
# Log a message at the info level. The shim is silent.
1820
def self.info(...)
1921
end
2022

23+
# Log a message at the warn level. The shim redirects to `Kernel#warn`.
2124
def self.warn(*arguments, exception: nil, **options)
2225
if exception
2326
super(*arguments, exception.full_message, **options)
@@ -26,10 +29,12 @@ def self.warn(*arguments, exception: nil, **options)
2629
end
2730
end
2831

32+
# Log a message at the error level. The shim redirects to `Kernel#warn`.
2933
def self.error(...)
3034
self.warn(...)
3135
end
3236

37+
# Log a message at the fatal level. The shim redirects to `Kernel#warn`.
3338
def self.fatal(...)
3439
self.warn(...)
3540
end

lib/async/idler.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ module Async
77
# A load balancing mechanism that can be used process work when the system is idle.
88
class Idler
99
# Create a new idler.
10-
# @public Since `stable-v2`.
10+
#
11+
# @public Since *Async v2*.
1112
#
1213
# @parameter maximum_load [Numeric] The maximum load before we start shedding work.
1314
# @parameter backoff [Numeric] The initial backoff time, used for delaying work.

lib/async/notification.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
module Async
99
# A synchronization primitive, which allows fibers to wait until a notification is received. Does not block the task which signals the notification. Waiting tasks are resumed on next iteration of the reactor.
10-
# @public Since `stable-v1`.
10+
# @public Since *Async v1*.
1111
class Notification < Condition
1212
# Signal to a given task that it should resume operations.
1313
def signal(value = nil, task: Task.current)

lib/async/queue.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module Async
1212
#
1313
# It has a compatible interface with {Notification} and {Condition}, except that it's multi-value.
1414
#
15-
# @public Since `stable-v1`.
15+
# @public Since *Async v1*.
1616
class Queue
1717
# Create a new queue.
1818
#
@@ -99,7 +99,7 @@ def wait
9999
end
100100

101101
# A queue which limits the number of items that can be enqueued.
102-
# @public Since `stable-v1`.
102+
# @public Since *Async v1*.
103103
class LimitedQueue < Queue
104104
# Create a new limited queue.
105105
#

lib/async/scheduler.rb

+93-23
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ def initialize(message = "Scheduler is closed!")
2727
end
2828

2929
# Whether the fiber scheduler is supported.
30-
# @public Since `stable-v1`.
30+
# @public Since *Async v1*.
3131
def self.supported?
3232
true
3333
end
3434

3535
# Create a new scheduler.
3636
#
37-
# @public Since `stable-v1`.
37+
# @public Since *Async v1*.
3838
# @parameter parent [Node | Nil] The parent node to use for task hierarchy.
3939
# @parameter selector [IO::Event::Selector] The selector to use for event handling.
4040
def initialize(parent = nil, selector: nil)
@@ -52,6 +52,7 @@ def initialize(parent = nil, selector: nil)
5252
end
5353

5454
# Compute the scheduler load according to the busy and idle times that are updated by the run loop.
55+
#
5556
# @returns [Float] The load of the scheduler. 0.0 means no load, 1.0 means fully loaded or over-loaded.
5657
def load
5758
total_time = @busy_time + @idle_time
@@ -95,7 +96,7 @@ def terminate
9596
end
9697

9798
# Terminate all child tasks and close the scheduler.
98-
# @public Since `stable-v1`.
99+
# @public Since *Async v1*.
99100
def close
100101
self.run_loop do
101102
until self.terminate
@@ -115,7 +116,7 @@ def close
115116
end
116117

117118
# @returns [Boolean] Whether the scheduler has been closed.
118-
# @public Since `stable-v1`.
119+
# @public Since *Async v1*.
119120
def closed?
120121
@selector.nil?
121122
end
@@ -167,6 +168,8 @@ def resume(fiber, *arguments)
167168
end
168169

169170
# Invoked when a fiber tries to perform a blocking operation which cannot continue. A corresponding call {unblock} must be performed to allow this fiber to continue.
171+
#
172+
170173
# @asynchronous May only be called on same thread as fiber scheduler.
171174
def block(blocker, timeout)
172175
# $stderr.puts "block(#{blocker}, #{Fiber.current}, #{timeout})"
@@ -190,7 +193,13 @@ def block(blocker, timeout)
190193
timer&.cancel!
191194
end
192195

196+
# Unblock a fiber that was previously blocked.
197+
#
198+
# @public Since *Async v2* and *Ruby v3.1*.
193199
# @asynchronous May be called from any thread.
200+
#
201+
# @parameter blocker [Object] The object that was blocking the fiber.
202+
# @parameter fiber [Fiber] The fiber to unblock.
194203
def unblock(blocker, fiber)
195204
# $stderr.puts "unblock(#{blocker}, #{fiber})"
196205

@@ -201,7 +210,12 @@ def unblock(blocker, fiber)
201210
end
202211
end
203212

204-
# @asynchronous May be non-blocking..
213+
# Sleep for the specified duration.
214+
#
215+
# @public Since *Async v2* and *Ruby v3.1*.
216+
# @asynchronous May be non-blocking.
217+
#
218+
# @parameter duration [Numeric | Nil] The time in seconds to sleep, or if nil, indefinitely.
205219
def kernel_sleep(duration = nil)
206220
if duration
207221
self.block(nil, duration)
@@ -210,15 +224,19 @@ def kernel_sleep(duration = nil)
210224
end
211225
end
212226

213-
# @asynchronous May be non-blocking..
227+
# Resolve the address of the given hostname.
228+
#
229+
# @public Since *Async v2*.
230+
# @asynchronous May be non-blocking.
231+
#
232+
# @parameter hostname [String] The hostname to resolve.
214233
def address_resolve(hostname)
215234
# On some platforms, hostnames may contain a device-specific suffix (e.g. %en0). We need to strip this before resolving.
216235
# See <https://github.com/socketry/async/issues/180> for more details.
217236
hostname = hostname.split("%", 2).first
218237
::Resolv.getaddresses(hostname)
219238
end
220239

221-
222240
if IO.method_defined?(:timeout)
223241
private def get_timeout(io)
224242
io.timeout
@@ -229,7 +247,14 @@ def address_resolve(hostname)
229247
end
230248
end
231249

232-
# @asynchronous May be non-blocking..
250+
# Wait for the specified IO to become ready for the specified events.
251+
#
252+
# @public Since *Async v2*.
253+
# @asynchronous May be non-blocking.
254+
#
255+
# @parameter io [IO] The IO object to wait on.
256+
# @parameter events [Integer] The events to wait for, e.g. `IO::READABLE`, `IO::WRITABLE`, etc.
257+
# @parameter timeout [Float | Nil] The maximum time to wait, or if nil, indefinitely.
233258
def io_wait(io, events, timeout = nil)
234259
fiber = Fiber.current
235260

@@ -251,6 +276,15 @@ def io_wait(io, events, timeout = nil)
251276
end
252277

253278
if ::IO::Event::Support.buffer?
279+
# Read from the specified IO into the buffer.
280+
#
281+
# @public Since *Async v2* and Ruby with `IO::Buffer` support.
282+
# @asynchronous May be non-blocking.
283+
#
284+
# @parameter io [IO] The IO object to read from.
285+
# @parameter buffer [IO::Buffer] The buffer to read into.
286+
# @parameter length [Integer] The minimum number of bytes to read.
287+
# @parameter offset [Integer] The offset within the buffer to read into.
254288
def io_read(io, buffer, length, offset = 0)
255289
fiber = Fiber.current
256290

@@ -266,6 +300,15 @@ def io_read(io, buffer, length, offset = 0)
266300
end
267301

268302
if RUBY_ENGINE != "ruby" || RUBY_VERSION >= "3.3.1"
303+
# Write the specified buffer to the IO.
304+
#
305+
# @public Since *Async v2* and *Ruby v3.3.1* with `IO::Buffer` support.
306+
# @asynchronous May be non-blocking.
307+
#
308+
# @parameter io [IO] The IO object to write to.
309+
# @parameter buffer [IO::Buffer] The buffer to write from.
310+
# @parameter length [Integer] The minimum number of bytes to write.
311+
# @parameter offset [Integer] The offset within the buffer to write from.
269312
def io_write(io, buffer, length, offset = 0)
270313
fiber = Fiber.current
271314

@@ -283,6 +326,10 @@ def io_write(io, buffer, length, offset = 0)
283326
end
284327

285328
# Wait for the specified process ID to exit.
329+
#
330+
# @public Since *Async v2*.
331+
# @asynchronous May be non-blocking.
332+
#
286333
# @parameter pid [Integer] The process ID to wait for.
287334
# @parameter flags [Integer] A bit-mask of flags suitable for `Process::Status.wait`.
288335
# @returns [Process::Status] A process status instance.
@@ -335,7 +382,10 @@ def process_wait(pid, flags)
335382
end
336383

337384
# Run one iteration of the event loop.
338-
# Does not handle interrupts.
385+
#
386+
# @public Since *Async v1*.
387+
# @asynchronous Must be invoked from blocking (root) fiber.
388+
#
339389
# @parameter timeout [Float | Nil] The maximum timeout, or if nil, indefinite.
340390
# @returns [Boolean] Whether there is more work to do.
341391
def run_once(timeout = nil)
@@ -354,6 +404,7 @@ def run_once(timeout = nil)
354404
end
355405

356406
# Checks and clears the interrupted state of the scheduler.
407+
#
357408
# @returns [Boolean] Whether the reactor has been interrupted.
358409
private def interrupted?
359410
if @interrupted
@@ -368,7 +419,9 @@ def run_once(timeout = nil)
368419
return false
369420
end
370421

371-
# Stop all children, including transient children, ignoring any signals.
422+
# Stop all children, including transient children.
423+
#
424+
# @public Since *Async v1*.
372425
def stop
373426
@children&.each do |child|
374427
child.stop
@@ -387,6 +440,7 @@ def stop
387440
end
388441
end
389442
rescue Interrupt => interrupt
443+
# If an interrupt did occur during an iteration of the event loop, we need to handle it. More specifically, `self.stop` is not safe to interrupt without potentially corrupting the task tree.
390444
Thread.handle_interrupt(::SignalException => :never) do
391445
Console.debug(self) do |buffer|
392446
buffer.puts "Scheduler interrupted: #{interrupt.inspect}"
@@ -406,6 +460,13 @@ def stop
406460
end
407461

408462
# Run the reactor until all tasks are finished. Proxies arguments to {#async} immediately before entering the loop, if a block is provided.
463+
#
464+
# Forwards all parameters to {#async} if a block is given.
465+
#
466+
# @public Since *Async v1*.
467+
#
468+
# @yields {|task| ...} The top level task, if a block is given.
469+
# @returns [Task] The initial task that was scheduled into the reactor.
409470
def run(...)
410471
Kernel.raise ClosedError if @selector.nil?
411472

@@ -418,30 +479,23 @@ def run(...)
418479
return initial_task
419480
end
420481

421-
# Start an asynchronous task within the specified reactor. The task will be
422-
# executed until the first blocking call, at which point it will yield and
423-
# and this method will return.
482+
# Start an asynchronous task within the specified reactor. The task will be executed until the first blocking call, at which point it will yield and and this method will return.
424483
#
425-
# This is the main entry point for scheduling asynchronus tasks.
484+
# @public Since *Async v1*.
485+
# @asynchronous May context switch immediately to new task.
486+
# @deprecated Use {#run} or {Task#async} instead.
426487
#
427488
# @yields {|task| ...} Executed within the task.
428489
# @returns [Task] The task that was scheduled into the reactor.
429-
# @deprecated With no replacement.
430490
def async(*arguments, **options, &block)
491+
# warn "Async::Scheduler#async is deprecated. Use `run` or `Task#async` instead.", uplevel: 1, category: :deprecated
492+
431493
Kernel.raise ClosedError if @selector.nil?
432494

433495
task = Task.new(Task.current? || self, **options, &block)
434496

435-
# I want to take a moment to explain the logic of this.
436-
# When calling an async block, we deterministically execute it until the
437-
# first blocking operation. We don't *have* to do this - we could schedule
438-
# it for later execution, but it's useful to:
439-
# - Fail at the point of the method call where possible.
440-
# - Execute determinstically where possible.
441-
# - Avoid scheduler overhead if no blocking operation is performed.
442497
task.run(*arguments)
443498

444-
# Console.debug "Initial execution of task #{fiber} complete (#{result} -> #{fiber.alive?})..."
445499
return task
446500
end
447501

@@ -450,7 +504,14 @@ def fiber(...)
450504
end
451505

452506
# Invoke the block, but after the specified timeout, raise {TimeoutError} in any currenly blocking operation. If the block runs to completion before the timeout occurs or there are no non-blocking operations after the timeout expires, the code will complete without any exception.
507+
#
508+
# @public Since *Async v1*.
509+
# @asynchronous May raise an exception at any interruption point (e.g. blocking operations).
510+
#
453511
# @parameter duration [Numeric] The time in seconds, in which the task should complete.
512+
# @parameter exception [Class] The exception class to raise.
513+
# @parameter message [String] The message to pass to the exception.
514+
# @yields {|duration| ...} The block to execute with a timeout.
454515
def with_timeout(duration, exception = TimeoutError, message = "execution expired", &block)
455516
fiber = Fiber.current
456517

@@ -465,6 +526,15 @@ def with_timeout(duration, exception = TimeoutError, message = "execution expire
465526
timer&.cancel!
466527
end
467528

529+
# Invoke the block, but after the specified timeout, raise the specified exception with the given message. If the block runs to completion before the timeout occurs or there are no non-blocking operations after the timeout expires, the code will complete without any exception.
530+
#
531+
# @public Since *Async v1* and *Ruby v3.1*. May be invoked from `Timeout.timeout`.
532+
# @asynchronous May raise an exception at any interruption point (e.g. blocking operations).
533+
#
534+
# @parameter duration [Numeric] The time in seconds, in which the task should complete.
535+
# @parameter exception [Class] The exception class to raise.
536+
# @parameter message [String] The message to pass to the exception.
537+
# @yields {|duration| ...} The block to execute with a timeout.
468538
def timeout_after(duration, exception, message, &block)
469539
with_timeout(duration, exception, message) do |timer|
470540
yield duration

lib/async/semaphore.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
module Async
99
# A synchronization primitive, which limits access to a given resource.
10-
# @public Since `stable-v1`.
10+
# @public Since *Async v1*.
1111
class Semaphore
1212
# @parameter limit [Integer] The maximum number of times the semaphore can be acquired before it blocks.
1313
# @parameter parent [Task | Semaphore | Nil] The parent for holding any children tasks.

0 commit comments

Comments
 (0)