SimFuture¶
Futures for cross-entity coordination. Generators yield futures to park until resolved.
SimFuture — yield on events, not just delays.
SimFuture enables generators to pause until an external condition is met, rather than only pausing for fixed time delays. When a generator yields a SimFuture, the process parks until another entity calls future.resolve(value).
This unlocks natural request-response modeling, resource acquisition, lock waiting, timeout races (any_of), and quorum waits (all_of).
Example::
class Client(Entity):
def handle_event(self, event):
future = SimFuture()
# Send request with the future so the server can resolve it
yield (
0.0,
[
Event(
time=self.now,
event_type="Request",
target=self.server,
context={"reply_future": future},
)
],
)
response = yield future # Park until server resolves
# response is the value passed to future.resolve(value)
class Server(Entity):
def handle_event(self, event):
yield 0.1 # Processing time
event.context["reply_future"].resolve({"status": "ok"})
SimFuture ¶
A future that generators can yield to park until resolved.
When a generator yields a SimFuture, the ProcessContinuation parks instead of scheduling a time-based resume. The generator stays suspended until some other entity calls resolve(value), at which point a new continuation is scheduled to resume the generator with the resolved value via gen.send(value).
Each SimFuture can only be yielded by one generator. For broadcast patterns, create separate futures per consumer.
Attributes:
| Name | Type | Description |
|---|---|---|
is_resolved |
bool
|
True if the future has been resolved. |
value |
Any
|
The resolved value (raises RuntimeError if not yet resolved). |
value
property
¶
The resolved value.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the future hasn't been resolved yet. |
resolve ¶
Resolve the future with a value, resuming the parked generator.
The parked generator will be resumed at the current simulation time with the value sent via gen.send(value). If no generator is parked yet, the value is stored and the generator will resume immediately when it yields this future.
Resolving an already-resolved future is a no-op.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
The value to send into the generator. |
None
|
any_of ¶
Return a future that resolves when ANY input future resolves.
The composite future resolves with a tuple (index, value) where
index is the position of the first future to resolve and value
is its resolved value.
This enables timeout races and first-to-complete patterns::
timeout = SimFuture()
# Schedule a timeout event that resolves timeout future
yield (
0.0,
[
Event.once(
time=self.now + 5.0,
event_type="Timeout",
fn=lambda e: timeout.resolve("timeout"),
)
],
)
response = SimFuture()
# Send request with response future
yield (
0.0,
[
Event(
time=self.now,
event_type="Request",
target=server,
context={"reply_future": response},
)
],
)
idx, value = yield any_of(timeout, response)
if idx == 0:
print("Timed out!")
else:
print(f"Got response: {value}")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*futures
|
SimFuture
|
Two or more SimFuture instances to race. |
()
|
Returns:
| Type | Description |
|---|---|
SimFuture
|
A new SimFuture that resolves when any input resolves. |
all_of ¶
Return a future that resolves when ALL input futures resolve.
The composite future resolves with a list of values in the same order as the input futures.
This enables quorum waits and barrier patterns::
ack1, ack2, ack3 = SimFuture(), SimFuture(), SimFuture()
# Send requests to three replicas
yield (
0.0,
[
Event(time=self.now, event_type="Write", target=replica1, context={"ack": ack1}),
Event(time=self.now, event_type="Write", target=replica2, context={"ack": ack2}),
Event(time=self.now, event_type="Write", target=replica3, context={"ack": ack3}),
],
)
results = yield all_of(ack1, ack2, ack3)
# results = [value1, value2, value3]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*futures
|
SimFuture
|
Two or more SimFuture instances to wait on. |
()
|
Returns:
| Type | Description |
|---|---|
SimFuture
|
A new SimFuture that resolves when all inputs resolve. |