Class: Ratomic::Pool
- Inherits:
-
Object
- Object
- Ratomic::Pool
- Defined in:
- lib/ratomic/pool.rb
Overview
A Ractor-safe ownership-transfer pool for mutable Ruby objects.
Pool follows a Rust-inspired ownership-transfer model: a pooled object has one active owner at a time. #checkout moves ownership from the pool to the caller; #checkin moves ownership back to the pool. Ruby enforces stale caller references dynamically with Ractor::MovedError.
This is ownership transfer, not borrowing. Pool never lends shared mutable references across Ractors.
Pool uses a private coordinator Ractor and caller-owned Ractor::Port reply ports. Objects are moved to callers on checkout and moved back to the pool on checkin. This is intentionally different from sharing the same mutable object between Ractors: at any instant, exactly one Ractor owns a checked-out object.
Instance Method Summary collapse
-
#checkin(object) ⇒ nil
Return an object to the pool.
-
#checkout ⇒ Object?
Checkout one object from the pool.
-
#initialize(size = 5, timeout = 1.0) ⇒ Pool
constructor
Create a pool and seed it with
sizeobjects from the factory block. -
#with {|object| ... } ⇒ Object
Checkout an object, yield it, then move it back to the pool.
Constructor Details
#initialize(size = 5, timeout = 1.0) ⇒ Pool
Create a pool and seed it with size objects from the factory block.
34 35 36 37 38 39 40 41 42 43 |
# File 'lib/ratomic/pool.rb', line 34 def initialize(size = 5, timeout = 1.0) raise ArgumentError, "pool size must be positive" if size <= 0 raise LocalJumpError, "no block given" unless block_given? @timeout = timeout&.to_f @control = self.class.send(:new_control_ractor) size.times { @control.send([:checkin, yield], move: true) } freeze Ractor.make_shareable(self) end |
Instance Method Details
#checkin(object) ⇒ nil
Return an object to the pool.
This moves ownership from the caller back to the pool. The caller must not use the object after calling this method; Ruby raises Ractor::MovedError for stale references.
71 72 73 74 |
# File 'lib/ratomic/pool.rb', line 71 def checkin(object) @control.send([:checkin, object], move: true) nil end |
#checkout ⇒ Object?
Checkout one object from the pool.
The returned object has been moved from the pool to the caller. The caller owns it until it is passed to #checkin.
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/ratomic/pool.rb', line 51 def checkout reply = Ractor::Port.new request_id = reply.object_id @control << [:checkout, request_id, reply] receive_checkout_reply(reply) rescue Timeout::Error nil ensure @control << [:cancel, request_id] if request_id reply&.close unless reply&.closed? end |
#with {|object| ... } ⇒ Object
Checkout an object, yield it, then move it back to the pool.
This is the preferred API because it guarantees checkin through an ensure block. If checkout times out, raises Ratomic::Error and does not yield.
84 85 86 87 88 89 90 91 |
# File 'lib/ratomic/pool.rb', line 84 def with object = checkout raise Ratomic::Error, "pool checkout timeout" if object.nil? yield object ensure checkin(object) unless object.nil? end |