Make it possible to retract handles from other facets within one's actor
This commit is contained in:
parent
fffcd025ad
commit
f71b8b0790
|
@ -53,11 +53,11 @@ class Actor:
|
||||||
if not daemon:
|
if not daemon:
|
||||||
adjust_engine_inhabitant_count(1)
|
adjust_engine_inhabitant_count(1)
|
||||||
self.root = Facet(self, None)
|
self.root = Facet(self, None)
|
||||||
|
self.outbound = initial_assertions or {}
|
||||||
self.exit_reason = None # None -> running, True -> terminated OK, exn -> error
|
self.exit_reason = None # None -> running, True -> terminated OK, exn -> error
|
||||||
self.exit_hooks = []
|
self.exit_hooks = []
|
||||||
self._log = None
|
self._log = None
|
||||||
Turn.run(Facet(self, self.root, initial_assertions = initial_assertions),
|
Turn.run(Facet(self, self.root, set(self.outbound.keys())), stop_if_inert_after(boot_proc))
|
||||||
stop_if_inert_after(boot_proc))
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Actor:%s>' % (self.name,)
|
return '<Actor:%s>' % (self.name,)
|
||||||
|
@ -104,15 +104,24 @@ class Actor:
|
||||||
adjust_engine_inhabitant_count(-1)
|
adjust_engine_inhabitant_count(-1)
|
||||||
queue_task(finish_termination)
|
queue_task(finish_termination)
|
||||||
|
|
||||||
|
def _pop_outbound(self, handle, clear_from_source_facet):
|
||||||
|
e = self.outbound.pop(handle)
|
||||||
|
if e and clear_from_source_facet:
|
||||||
|
try:
|
||||||
|
e.source_facet.handles.remove(handle)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
return e
|
||||||
|
|
||||||
class Facet:
|
class Facet:
|
||||||
def __init__(self, actor, parent, initial_assertions = None):
|
def __init__(self, actor, parent, initial_handles=None):
|
||||||
self.id = next(_next_facet_id)
|
self.id = next(_next_facet_id)
|
||||||
self.actor = actor
|
self.actor = actor
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
if parent:
|
if parent:
|
||||||
parent.children.add(self)
|
parent.children.add(self)
|
||||||
self.children = set()
|
self.children = set()
|
||||||
self.outbound = initial_assertions or {}
|
self.handles = initial_handles or set()
|
||||||
self.shutdown_actions = []
|
self.shutdown_actions = []
|
||||||
self.linked_tasks = []
|
self.linked_tasks = []
|
||||||
self.alive = True
|
self.alive = True
|
||||||
|
@ -144,7 +153,7 @@ class Facet:
|
||||||
def isinert(self):
|
def isinert(self):
|
||||||
return \
|
return \
|
||||||
len(self.children) == 0 and \
|
len(self.children) == 0 and \
|
||||||
len(self.outbound) == 0 and \
|
len(self.handles) == 0 and \
|
||||||
len(self.linked_tasks) == 0 and \
|
len(self.linked_tasks) == 0 and \
|
||||||
self.inert_check_preventers == 0
|
self.inert_check_preventers == 0
|
||||||
|
|
||||||
|
@ -193,9 +202,11 @@ class Facet:
|
||||||
if orderly:
|
if orderly:
|
||||||
for h in self.shutdown_actions:
|
for h in self.shutdown_actions:
|
||||||
h(turn)
|
h(turn)
|
||||||
for e in self.outbound.values():
|
for h in self.handles:
|
||||||
turn._retract(e)
|
# Optimization: don't clear from source facet, the source facet is us and we're
|
||||||
self.outbound.clear()
|
# about to clear our handles in one fell swoop.
|
||||||
|
turn._retract(self.actor._pop_outbound(h, clear_from_source_facet=False))
|
||||||
|
self.handles.clear()
|
||||||
|
|
||||||
if orderly:
|
if orderly:
|
||||||
if parent:
|
if parent:
|
||||||
|
@ -298,12 +309,13 @@ class Turn:
|
||||||
def on_stop(self, a):
|
def on_stop(self, a):
|
||||||
self._facet.on_stop(a)
|
self._facet.on_stop(a)
|
||||||
|
|
||||||
def spawn(self, boot_proc, name = None, initial_assertions = None, daemon = False):
|
def spawn(self, boot_proc, name = None, initial_handles = None, daemon = False):
|
||||||
def action(turn):
|
def action(turn):
|
||||||
new_outbound = {}
|
new_outbound = {}
|
||||||
if initial_assertions is not None:
|
if initial_handles is not None:
|
||||||
for handle in initial_assertions:
|
for handle in initial_handles:
|
||||||
new_outbound[handle] = self._facet.outbound.pop(handle)
|
new_outbound[handle] = \
|
||||||
|
self._facet.actor._pop_outbound(handle, clear_from_source_facet=True)
|
||||||
queue_task(lambda: Actor(boot_proc,
|
queue_task(lambda: Actor(boot_proc,
|
||||||
name = name,
|
name = name,
|
||||||
initial_assertions = new_outbound,
|
initial_assertions = new_outbound,
|
||||||
|
@ -324,8 +336,10 @@ class Turn:
|
||||||
def _publish(self, ref, assertion, handle):
|
def _publish(self, ref, assertion, handle):
|
||||||
# TODO: attenuation
|
# TODO: attenuation
|
||||||
assertion = preserve(assertion)
|
assertion = preserve(assertion)
|
||||||
e = OutboundAssertion(handle, ref)
|
facet = self._facet
|
||||||
self._facet.outbound[handle] = e
|
e = OutboundAssertion(facet, handle, ref)
|
||||||
|
facet.actor.outbound[handle] = e
|
||||||
|
facet.handles.add(handle)
|
||||||
def action(turn):
|
def action(turn):
|
||||||
e.established = True
|
e.established = True
|
||||||
self.log.debug('%r <-- publish %r handle %r', ref, assertion, handle)
|
self.log.debug('%r <-- publish %r handle %r', ref, assertion, handle)
|
||||||
|
@ -334,7 +348,7 @@ class Turn:
|
||||||
|
|
||||||
def retract(self, handle):
|
def retract(self, handle):
|
||||||
if handle is not None:
|
if handle is not None:
|
||||||
e = self._facet.outbound.pop(handle, None)
|
e = self._facet.actor._pop_outbound(handle, clear_from_source_facet=True)
|
||||||
if e is not None:
|
if e is not None:
|
||||||
self._retract(e)
|
self._retract(e)
|
||||||
|
|
||||||
|
@ -344,7 +358,8 @@ class Turn:
|
||||||
return new_handle
|
return new_handle
|
||||||
|
|
||||||
def _retract(self, e):
|
def _retract(self, e):
|
||||||
# Assumes e has already been removed from self._facet.outbound
|
# Assumes e has already been removed from self._facet.actor.outbound and the
|
||||||
|
# appropriate set of handles
|
||||||
def action(turn):
|
def action(turn):
|
||||||
if e.established:
|
if e.established:
|
||||||
e.established = False
|
e.established = False
|
||||||
|
@ -408,14 +423,15 @@ class Ref:
|
||||||
return '<Ref:%s/%r>' % (self.facet._repr_labels(), self.entity)
|
return '<Ref:%s/%r>' % (self.facet._repr_labels(), self.entity)
|
||||||
|
|
||||||
class OutboundAssertion:
|
class OutboundAssertion:
|
||||||
def __init__(self, handle, ref):
|
def __init__(self, source_facet, handle, ref):
|
||||||
|
self.source_facet = source_facet
|
||||||
self.handle = handle
|
self.handle = handle
|
||||||
self.ref = ref
|
self.ref = ref
|
||||||
self.established = False
|
self.established = False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<OutboundAssertion handle=%s ref=%r%s>' % \
|
return '<OutboundAssertion src=%r handle=%s ref=%r%s>' % \
|
||||||
(self.handle, self.ref, ' established' if self.established else '')
|
(self.source_facet, self.handle, self.ref, ' established' if self.established else '')
|
||||||
|
|
||||||
# Can act as a mixin
|
# Can act as a mixin
|
||||||
class Entity:
|
class Entity:
|
||||||
|
|
Loading…
Reference in New Issue