Skip to content

Commit e07d99f

Browse files
committed
refactor and drop dependency on Async::IO
1 parent 42579d4 commit e07d99f

File tree

14 files changed

+283
-349
lines changed

14 files changed

+283
-349
lines changed

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
next
2+
-----
3+
* refactor to make code Fiber Scheduler agnostic
4+
* remove Async::IO::CZTopSocket
5+
16
1.1.1 (1/4/2024)
27
-----
38
* speed up Async::IO#wait_readable and #wait_writable

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,22 @@ mechanisms (like CURVE).
1313

1414
## Example with Async
1515

16-
See [this example](https://github.com/paddor/cztop/blob/master/examples/async/):
16+
See [this example](https://github.com/paddor/cztop/blob/master/examples/async.rb):
1717

1818
```ruby
1919
#! /usr/bin/env ruby
2020

21-
require 'cztop/async'
21+
require 'cztop'
2222

2323
Async do |task|
2424
task.async do |t|
2525
socket = CZTop::Socket::REP.new("inproc://req_rep_example")
26-
io = Async::IO.try_convert socket
27-
2826
socket.options.rcvtimeo = 50 # ms
2927

3028
loop do
31-
msg = io.receive
29+
msg = socket.receive
3230
puts "<<< #{msg.to_a.inspect}"
33-
io << msg.to_a.map(&:upcase)
31+
socket << msg.to_a.map(&:upcase)
3432
rescue IO::TimeoutError
3533
break
3634
end
@@ -40,11 +38,10 @@ Async do |task|
4038

4139
task.async do
4240
socket = CZTop::Socket::REQ.new("inproc://req_rep_example")
43-
io = Async::IO.try_convert socket
4441

4542
10.times do |i|
46-
io << "foobar ##{i}"
47-
msg = io.receive
43+
socket << "foobar ##{i}"
44+
msg = socket.receive
4845
puts ">>> #{msg.to_a.inspect}"
4946
end
5047

@@ -56,9 +53,8 @@ end
5653

5754
Output:
5855
```
59-
$ cd examples/async
60-
$ bundle
61-
$ /bin/time bundle exec ./async.rb
56+
$ cd examples
57+
$ time ./async.rb
6258
<<< ["foobar #0"]
6359
>>> ["FOOBAR #0"]
6460
<<< ["foobar #1"]
@@ -81,16 +77,20 @@ $ /bin/time bundle exec ./async.rb
8177
>>> ["FOOBAR #9"]
8278
REQ done.
8379
REP done.
84-
0.46user 0.09system 0:00.60elapsed 90%CPU (0avgtext+0avgdata 47296maxresident)k
85-
0inputs+0outputs (0major+13669minor)pagefaults 0swaps
80+
81+
________________________________________________________
82+
Executed in 401.51 millis fish external
83+
usr time 308.44 millis 605.00 micros 307.83 millis
84+
sys time 40.08 millis 278.00 micros 39.81 millis
85+
8686
```
8787

8888
## Overview
8989

9090
### Features
9191

9292
* Ruby idiomatic API
93-
* compatible with [Async](https://github.com/socketry/async) / [Async::IO](https://github.com/socketry/async-io)
93+
* Fiber Scheduler aware
9494
* errors as exceptions
9595
* CURVE security
9696
* supports CZMQ DRAFT API

cztop.gemspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,5 @@ Gem::Specification.new do |spec|
3636

3737
if RUBY_VERSION >= '3.1'
3838
spec.add_development_dependency "async", ">= 2.0.1"
39-
spec.add_development_dependency "async-io"
4039
end
4140
end

examples/async/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

examples/async/README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

examples/async/async.rb

Lines changed: 0 additions & 44 deletions
This file was deleted.

lib/cztop/async.rb

Lines changed: 0 additions & 124 deletions
This file was deleted.

lib/cztop/message.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def empty?
6161
# returns with failure. Please report as bug.
6262
#
6363
def send_to(destination)
64+
destination.wait_writable if Fiber.scheduler
65+
6466
rc = Zmsg.send(ffi_delegate, destination)
6567
return if rc.zero?
6668

@@ -79,6 +81,8 @@ def send_to(destination)
7981
# @raise [SystemCallError] for any other error code set after +zmsg_recv+
8082
# returns with failure. Please report as bug.
8183
def self.receive_from(source)
84+
source.wait_readable if Fiber.scheduler
85+
8286
delegate = Zmsg.recv(source)
8387
return from_ffi_delegate(delegate) unless delegate.null?
8488

lib/cztop/send_receive_methods.rb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,80 @@ def receive
3535
Message.receive_from(self)
3636
end
3737

38+
39+
# Waits for socket to become readable.
40+
def wait_readable(timeout = read_timeout)
41+
return true if readable?
42+
43+
@fd_io ||= to_io
44+
45+
if timeout
46+
timeout_at = now + timeout
47+
48+
while true
49+
@fd_io.wait_readable(timeout)
50+
break if readable? # NOTE: ZMQ FD can't be trusted 100%
51+
raise ::IO::TimeoutError if now >= timeout_at
52+
end
53+
else
54+
@fd_io.wait_readable until readable?
55+
end
56+
end
57+
58+
59+
# Waits for socket to become writable.
60+
def wait_writable(timeout = write_timeout)
61+
return true if writable?
62+
63+
@fd_io ||= to_io
64+
65+
if timeout
66+
timeout_at = now + timeout
67+
68+
while true
69+
@fd_io.wait_writable(timeout)
70+
break if writable? # NOTE: ZMQ FD can't be trusted 100%
71+
raise ::IO::TimeoutError if now >= timeout_at
72+
end
73+
else
74+
@fd_io.wait_writable until writable?
75+
end
76+
end
77+
78+
79+
# @return [Float, nil] the timeout in seconds used by {IO#wait_readable}
80+
def read_timeout
81+
timeout = options.rcvtimeo
82+
83+
if timeout <= 0
84+
timeout = nil
85+
else
86+
timeout = timeout.to_f / 1000
87+
end
88+
89+
timeout
90+
end
91+
92+
93+
# @return [Float, nil] the timeout in seconds used by {IO#wait_writable}
94+
def write_timeout
95+
timeout = options.sndtimeo
96+
97+
if timeout <= 0
98+
timeout = nil
99+
else
100+
timeout = timeout.to_f / 1000
101+
end
102+
103+
timeout
104+
end
105+
106+
107+
private
108+
109+
110+
def now
111+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
112+
end
38113
end
39114
end

lib/cztop/zsock_options.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ def fd
4343
end
4444

4545

46+
# @return [IO] IO for FD
47+
def to_io
48+
IO.for_fd fd, autoclose: false
49+
end
50+
51+
4652
# Used to access the options of a {Socket} or {Actor}.
4753
class OptionsAccessor
4854

0 commit comments

Comments
 (0)