@@ -45,3 +45,58 @@ def decorator(func):
4545 with CS (cowns , * args ):
4646 return func ()
4747 return decorator
48+
49+ # TODO: this creates a normal Python thread and ensures that all its
50+ # arguments are moved to the new thread. Eventually we should revisit
51+ # this behaviour as we go multiple interpreters / multicore.
52+ # TODO: require RC to be one less when move is upstreamed
53+ def PyronaThread (group = None , target = None , name = None ,
54+ args = (), kwargs = None , * , daemon = None ):
55+ # Only check when a program uses pyrona
56+ from sys import getrefcount as rc
57+ from threading import Thread
58+ # TODO: improve this check for final version of phase 3
59+ # - Revisit the rc checks
60+ # - Consider throwing a different kind of error (e.g. RegionError)
61+ # - Improve error messages
62+ def ok_share (o ):
63+ if isimmutable (o ):
64+ return True
65+ if isinstance (o , Cown ):
66+ return True
67+ return False
68+ def ok_move (o ):
69+ if isinstance (o , Region ):
70+ if rc (o ) != 5 :
71+ # rc = 4 because:
72+ # 1. ref to o in rc
73+ # 2. ref to o on this frame (ok_move)
74+ # 3. ref to o on the calling frame (check)
75+ # 4. ref to o from iteration over kwargs dictionary or args tuple/list
76+ # 5. ref to o from kwargs dictionary or args tuple/list
77+ raise RuntimeError ("Region passed to thread was not moved into thread" )
78+ if o .is_open ():
79+ raise RuntimeError ("Region passed to thread was open" )
80+ return True
81+ return False
82+
83+ def check (a , args ):
84+ # rc(args) == 4 because we need to know that the args list is moved into the thread too
85+ # rc = 4 because:
86+ # 1. ref to args in rc
87+ # 2. ref to args on this frame
88+ # 3. ref to args on the calling framedef check(a, args):
89+ # 4. ref from frame calling PyronaThread -- FIXME: not valid; revisit after #45
90+ if not (ok_share (a ) or (ok_move (a ) and rc (args ) == 4 )):
91+ raise RuntimeError ("Thread was passed an object which was neither immutable, a cown, or a unique region" )
92+
93+ if kwargs is None :
94+ for a in args :
95+ check (a , args )
96+ return Thread (group , target , name , args , daemon )
97+ else :
98+ for k in kwargs :
99+ # Important to get matching RCs in both paths
100+ v = kwargs [k ]
101+ check (v , kwargs )
102+ return Thread (group , target , name , kwargs , daemon )
0 commit comments