State Sharing#
State sharing is a way to share a state on an actor between multiple task networks.
The only currently implemented feature that shares state is the SharedLinearChangingState
.
This is an advanced feature that will require a user to subclass and create their own sharing state for their specific use case.
Creating Your Own#
There’s no explicit API for defining your own sharing state, other than to subclass from State or ActiveState and go from there.
This is because, while UPSTAGE wants to enforce many good practices, it’s difficult to enforce a particular workflow from state changes back to the task network. This is why the Nucleus must be explicitly defined and why it also uses interrupts, rather than another concept, to manage state changes.
In some cases, you may be able to get away with pure decrements:
class Thinker(UP.Actor):
cognition = UP.State[float](valid_types=float, default=1.0)
class DoThinking(UP.Task):
def task(self, *, actor: Thinker):
task_cognition_needs = self.get_actor_knowledge(actor, "brain power")
if actor.cognition < task_cognition_needs:
raise UP.SimulationError("Not enough brain power!")
actor.cognition -= task_cognition_needs
yield UP.Wait(some_time_for_task)
actor.cognition += task_cognition_needs
If you do that mechanism, you’ll need to handle interrupts that remember how much decrement you applied, then put it back.
A more difficult use case is a shared state that follows a “allocate full, but someone can use some and you get less” pattern. There’s an example of that in Task Nucleus. That concept won’t work directly with an ActiveState because you would need to restart the task to modify time to complete - which would de-allocate and cause some looping problems in the nucleus.
In general, a shared state is best for when each task just uses or changes part of the state without concern for the other tasks. Nucleus is probably the better way to handle everything else.