Demo of relay refcounting subtlety

This commit is contained in:
Tony Garnock-Jones 2021-09-07 14:57:35 +02:00
parent d6dc75e41d
commit 4821f32e8b
1 changed files with 83 additions and 0 deletions

83
bidi-gc.py Normal file
View File

@ -0,0 +1,83 @@
import sys
import argparse
import asyncio
import random
import syndicate
from syndicate import patterns as P, actor, dataspace, Record, Embedded
from syndicate.during import Handler
from syndicate.schema import sturdy
parser = argparse.ArgumentParser(description='Test bidirectional object reference GC.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--address', metavar='\'<tcp "HOST" PORT>\'',
help='transport address of the server',
default='<ws "ws://localhost:8001/">')
parser.add_argument('--cap', metavar='\'<ref ...>\'',
help='capability for the dataspace on the server',
default='<ref "syndicate" [] #[pkgN9TBmEd3Q04grVG4Zdw==]>')
parser.add_argument('--start',
help='make this instance kick off the procedure',
action='store_true')
args = parser.parse_args()
# A B DS
# ----- ----- ------
#
# ---1:Boot(b)---o
#
# ------2:Observe(Boot($))-----o
# o----------3:[b]--------------
#
# ---4:One(a)---o
#
# -------1-------x
# x------------3----------------
#
# (At this point, B has no outgoing
# assertions, but has one incoming
# assertion.)
#
# o---5:Two()----
#
# ----Three()--->
Boot = Record.makeConstructor('Boot', 'b')
One = Record.makeConstructor('One', 'a')
Two = Record.makeConstructor('Two', '')
Three = Record.makeConstructor('Three', '')
@actor.run_system(name = 'bidi-gc', debug = False)
def main(turn):
root_facet = turn._facet
@syndicate.relay.connect(turn, args.address, sturdy.SturdyRef.decode(syndicate.parse(args.cap)),
on_disconnected = lambda _relay, _did_connect: sys.exit(1))
def on_connected(turn, ds):
if args.start:
# We are "A".
@dataspace.observe(turn, ds, P.rec('Boot', P.CAPTURE))
@Handler().add_handler
def on_b(turn, b):
print('A got B', b)
@Handler().add_handler
def a(turn, two):
print('A got assertion:', two)
turn.send(b.embeddedValue, Three())
return lambda turn: print('Assertion', two, 'from B went')
turn.publish(b.embeddedValue, One(Embedded(turn.ref(a))))
return lambda turn: print('B\'s Boot record went')
else:
# We are "B".
@Handler().add_handler
def b(turn, one):
print('B got assertion:', one)
print('boot_handle =', boot_handle)
turn.retract(boot_handle)
turn.publish(One._a(one).embeddedValue, Two())
return lambda turn: print('B facet stopping')
@b.msg_handler
def b_msg(turn, three):
print('B got message: ', three)
boot_handle = turn.publish(ds, Boot(Embedded(turn.ref(b))))