[pypy-svn] r30118 - in pypy/dist/pypy/objspace: . constraint/applevel constraint/test
auc at codespeak.net
auc at codespeak.net
Mon Jul 17 14:40:26 CEST 2006
Author: auc
Date: Mon Jul 17 14:40:22 2006
New Revision: 30118
Modified:
pypy/dist/pypy/objspace/constraint/applevel/solver.py
pypy/dist/pypy/objspace/constraint/test/test_btree.py
pypy/dist/pypy/objspace/logic.py
Log:
(auc, david) basic working scheduler
Modified: pypy/dist/pypy/objspace/constraint/applevel/solver.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/applevel/solver.py (original)
+++ pypy/dist/pypy/objspace/constraint/applevel/solver.py Mon Jul 17 14:40:22 2006
@@ -40,3 +40,64 @@
print ' '*len(sp_stack), "dead-end"
solve = lazily_iter_solve_all
+
+
+#-- dfs with recomputations
+
+class Chain(object):
+ def __init__(self, space=None, parent=None, distance=1):
+ self.space = space
+ self.parent = parent
+ self.distance = distance
+ self.child = None
+ self.last_branch = None
+ def set_branches(self, branches):
+ self.branches = range(branches)
+ def collect_space(self, space):
+ self.child = Chain(space, parent=self,
+ distance=self.distance + 1)
+ return self.child
+ def clone_time(self):
+ return self.distance % recomputation_distance
+
+def dfs_with_recomputations(space, recomputation_distance=1):
+ assert recomputation_distance > 0
+
+ node = Chain(space)
+
+ def get_space():
+ # XXX: write me
+ pass
+
+ while node:
+ space = get_space()
+ status = space.ask()
+ if status == 1:
+ yield space.merge()
+ elif status > 1:
+ if node.clone_time():
+ clone = space.clone()
+ if node.child is None:
+ node.set_branges(status)
+ branch = node.branches.pop()
+ node.last_branch = branch # recomputation info
+ node = node.collect(clone)
+ clone.commit(branch)
+ else:
+ #find previous clone_time node
+ cur = node.parent
+ while not cur.clone_time():
+ cur = cur.parent
+ # take a clone of the local space,
+ # replay all the branches
+ clone = cur.space.clone()
+ while cur.child:
+ clone.commit(cur.last_branch)
+ cur = cur.child
+ # now, do the new computation
+ # XXX: factor me out
+ assert cur is node
+ branch = node.branches.pop()
+ node.last_branch = branch
+ node = node.collect(None)
+ clone.commit(branch)
Modified: pypy/dist/pypy/objspace/constraint/test/test_btree.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_btree.py (original)
+++ pypy/dist/pypy/objspace/constraint/test/test_btree.py Mon Jul 17 14:40:22 2006
@@ -1,6 +1,5 @@
class TestBTree(object):
-
def test_everything_at_once(self):
from pypy.objspace.constraint.btree import BTree
b = BTree()
Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py (original)
+++ pypy/dist/pypy/objspace/logic.py Mon Jul 17 14:40:22 2006
@@ -12,6 +12,20 @@
from pypy.objspace.std.stringobject import W_StringObject
from pypy.objspace.std.model import StdObjSpaceMultiMethod
+# misc
+import os
+
+DEBUG = True
+def w(*msgs, **kwopt):
+ if not DEBUG: return
+ for msg in msgs:
+ os.write(1, str(msg))
+ os.write(1, ' ')
+ try:
+ if kwopt['LF']:
+ raise Exception
+ except:
+ os.write(1, ' \n')
#-- THE BUILTINS ----------------------------------------------------------------------
@@ -20,6 +34,8 @@
W_Root = baseobjspace.W_Root
Wrappable = baseobjspace.Wrappable
+#-- THREADING/COROUTINING -----------------------------------
+
USE_COROUTINES = True
HAVE_GREENLETS = True
try:
@@ -35,119 +51,207 @@
return HAVE_GREENLETS
return False
-if USE_COROUTINES:
- from pypy.module._stackless.coroutine import AppCoroutine, _AppThunk
+assert USE_COROUTINES # once & for all
+
+from pypy.module._stackless.coroutine import _AppThunk, AppCoState, Coroutine, ClonableCoroutine
- class ScheduleState(object):
- def __init__(self):
- self.runnable_uthreads = {}
- self.uthreads_blocked_on = {}
- self.uthreads_blocked_byneed = {}
- self.exhausting = 0
-
- def pop_runnable_thread(self):
- # umpf, no popitem in RPython
- key = None
- for key, item in self.runnable_uthreads.iteritems():
- break
- del self.runnable_uthreads[key]
- return key
-
- def add_to_runnable(self, uthread):
- assert isinstance(uthread, AppCoroutine)
- self.runnable_uthreads[uthread] = True
-
- def remove_from_runnable(self, uthread):
- assert isinstance(uthread, AppCoroutine)
- del self.runnable_uthreads[uthread]
-
- def have_runnable_threads(self):
- return bool(self.runnable_uthreads)
-
- def have_blocked_threads(self):
- return bool(self.uthreads_blocked_on)
-
- def add_to_blocked(self, w_var, uthread):
- assert isinstance(w_var, W_Var)
- assert isinstance(uthread, AppCoroutine)
- if w_var in self.uthreads_blocked_on:
- blocked = self.uthreads_blocked_on[w_var]
- else:
- blocked = []
- self.uthreads_blocked_on[w_var] = blocked
- blocked.append(uthread)
-
- def pop_blocked_on(self, w_var):
- assert isinstance(w_var, W_Var)
- if w_var not in self.uthreads_blocked_on:
- blocked = []
- else:
- blocked = self.uthreads_blocked_on[w_var]
- del self.uthreads_blocked_on[w_var]
- return blocked
-
- def add_to_blocked_byneed(self, w_var, uthread):
- assert isinstance(w_var, W_Var)
- assert isinstance(uthread, AppCoroutine)
- #print " adding", uthread, "to byneed on", w_var
- if w_var in self.uthreads_blocked_byneed:
- blocked = self.uthreads_blocked_byneed[w_var]
- else:
- blocked = []
- self.uthreads_blocked_byneed[w_var] = blocked
- blocked.append(uthread)
-
- def pop_blocked_byneed_on(self, w_var):
- assert isinstance(w_var, W_Var)
- if w_var not in self.uthreads_blocked_byneed:
- #print " there was nobody to remove for", w_var
- blocked = []
- else:
- blocked = self.uthreads_blocked_byneed[w_var]
- del self.uthreads_blocked_byneed[w_var]
- #print " removing", blocked, "from byneed on", w_var
- return blocked
-
-
- schedule_state = ScheduleState()
-
- class Thunk(_AppThunk):
- def __init__(self, space, state, w_callable, args, w_Result):
- _AppThunk.__init__(self, space, state, w_callable, args)
- self.w_Result = w_Result # the upper-case R is because it is a logic variable
-
- def call(self):
- costate = self.costate
- _AppThunk.call(self)
- bind(self.space, self.w_Result,
- costate.w_tempval)
-
- def uthread(space, w_callable, __args__):
- args = __args__.normalize()
- w_Result = W_Var()
- coro = AppCoroutine(space)
- state = coro.costate
- thunk = Thunk(space, state, w_callable, args, w_Result)
- coro.bind(thunk)
- current = AppCoroutine.w_getcurrent(space)
- schedule_state.add_to_runnable(current)
- coro.w_switch()
- if not schedule_state.exhausting:
- schedule_state.exhausting += 1
- while schedule_state.have_runnable_threads():
- next_coro = schedule_state.pop_runnable_thread()
- if next_coro.is_alive() and next_coro is not current:
- schedule_state.add_to_runnable(current)
- next_coro.w_switch()
- if schedule_state.exhausting > 1:
- break
- schedule_state.exhausting -= 1
- return w_Result
- app_uthread = gateway.interp2app(uthread, unwrap_spec=[baseobjspace.ObjSpace,
- baseobjspace.W_Root,
- argument.Arguments])
+def SETNEXT(obj, val):
+ obj.next = val
+
+def SETPREV(obj, val):
+ obj.prev = val
+
+def SETNONE(obj):
+ obj.prev = obj.next = None
+
+class Scheduler(object):
+
+ def __init__(self, space):
+ self.space = space
+ self._main = ClonableCoroutine.w_getcurrent(space)
+ self._init_head(self._main)
+ self._init_blocked()
+ w ("MAIN THREAD = ", id(self._main))
+
+ def _init_blocked(self):
+ self._blocked = {} # thread set
+ self._blocked_on = {} # var -> threads
+ self._blocked_byneed = {} # var -> threads
+
+ def _init_head(self, coro):
+ self._head = coro
+ self._head.next = self._head.prev = self._head
+
+ def _set_head(self, thread):
+ self._head = thread
+
+ def _check_initial_conditions(self):
+ try:
+ assert self._head.next == self._head.prev == self._head
+ assert self._head not in self._blocked
+ assert self._head not in self._blocked_on
+ assert self._head not in self._blocked_byneed
+ except:
+ self.display_head()
+ w("BLOCKED", self._blocked)
+ all = {}
+ all.update(self._blocked_on)
+ all.update(self._blocked_byneed)
+ w(all)
+ raise
+
+ def _chain_insert(self, thread):
+ assert thread.next is None
+ assert thread.prev is None
+ if self._head is None:
+ SETNEXT(thread, thread)
+ SETPREV(thread, thread)
+ self._set_head(thread)
+ else:
+ r = self._head
+ l = r.prev
+ SETNEXT(l, thread)
+ SETPREV(r, thread)
+ SETPREV(thread, l)
+ SETNEXT(thread, r)
+
+ def remove_thread(self, thread):
+ w(".. REMOVING", id(thread))
+ assert thread not in self._blocked
+ l = thread.prev
+ r = thread.next
+ SETNEXT(l, r)
+ SETPREV(r, l)
+ if r == thread:
+ w("DUH !")
+ self.display_head()
+ SETNONE(thread)
+ return thread
+
+ #-- to be used by logic objspace
+
+ def schedule(self):
+ to_be_run = self._select_next(lambda coro: coro in self._blocked)
+ w(".. SWITCHING", id(ClonableCoroutine.w_getcurrent(self.space)), "=>", id(to_be_run))
+ to_be_run.w_switch()
+
+ def _select_next(self, skip_condition):
+ """skip_condition is a predicate for NOT selecting one thread"""
+ to_be_run = self._head
+ sentinel = to_be_run
+ current = ClonableCoroutine.w_getcurrent(self.space)
+ while skip_condition(to_be_run) or to_be_run == current:
+ to_be_run = to_be_run.next
+ if to_be_run == sentinel:
+ self.display_head()
+ ## we RESET sched state so as to keep being usable beyond that
+ # (for instance, allow other tests to be run)
+ self._init_head(self._main)
+ self._init_blocked()
+ w(".. SCHEDULER reinitialized")
+ raise OperationError(self.space.w_RuntimeError,
+ self.space.wrap("can't schedule, possible deadlock in sight"))
+ return to_be_run
+
+ def display_head(self):
+ curr = self._head
+ w("HEAD : [prev, curr, next]", LF=False)
+ w([id(self._head.prev), id(self._head), id(self._head.next)], LF=False)
+ while curr.next != self._head:
+ curr = curr.next
+ w([id(curr.prev), id(curr), id(curr.next)], LF=False)
+ w()
+
+ def add_new_thread(self, thread):
+ "insert 'thread' at end of running queue"
+ self._chain_insert(thread)
+
+ def add_to_blocked_on(self, w_var, uthread):
+ w(".. we BLOCK thread", id(uthread), "on var", id(w_var))
+ assert isinstance(w_var, W_Var)
+ assert isinstance(uthread, Coroutine)
+ assert uthread not in self._blocked
+ if w_var in self._blocked_on:
+ blocked = self._blocked_on[w_var]
+ else:
+ blocked = []
+ self._blocked_on[w_var] = blocked
+ blocked.append(uthread)
+ self._blocked[uthread] = True
+
+ def unblock_on(self, w_var):
+ w(".. we UNBLOCK threads dependants of var", id(w_var), LF=False)
+ assert isinstance(w_var, W_Var)
+ blocked = []
+ if w_var in self._blocked_on:
+ blocked = self._blocked_on[w_var]
+ del self._blocked_on[w_var]
+ w([id(thr) for thr in blocked])
+ for thr in blocked: del self._blocked[thr]
+
+ def add_to_blocked_byneed(self, w_var, uthread):
+ w(".. we BLOCK BYNEED thread", id(uthread), "on var", id(w_var))
+ assert isinstance(w_var, W_Var)
+ assert isinstance(uthread, Coroutine)
+ if w_var in self._blocked_byneed:
+ blocked = self._blocked_byneed[w_var]
+ else:
+ blocked = []
+ self._blocked_byneed[w_var] = blocked
+ blocked.append(uthread)
+ self._blocked[uthread] = True
+
+ def unblock_byneed_on(self, space, w_var):
+ w(".. we UNBLOCK BYNEED dependants of var", id(w_var), LF=False)
+ assert isinstance(w_var, W_Var)
+ blocked = []
+ for w_alias in aliases(space, w_var):
+ if w_alias in self._blocked_byneed:
+ blocked += self._blocked_byneed[w_alias]
+ del self._blocked_byneed[w_alias]
+ w_alias.w_needed = True
+ w([id(thr) for thr in blocked])
+ for thr in blocked: del self._blocked[thr]
+
+scheduler = []
+
+class Thunk(_AppThunk):
+ def __init__(self, space, w_callable, args, w_Result, coro):
+ _AppThunk.__init__(self, space, coro.costate, w_callable, args)
+ self.w_Result = w_Result
+ self._coro = coro
+
+ def call(self):
+ _AppThunk.call(self)
+ # bind does not suffice for we can have a right-hand logic var
+ unify(self.space, self.w_Result, self.costate.w_tempval)
+ scheduler[0].remove_thread(self._coro)
+ scheduler[0].schedule()
+
+def uthread(space, w_callable, __args__):
+ args = __args__.normalize()
+ w_Future = W_Var()
+ # coro init
+ coro = ClonableCoroutine(space)
+ # prepare thread chaining, create missing slots
+ coro.next = coro.prev = None
+ # feed the coro
+ thunk = Thunk(space, w_callable, args, w_Future, coro)
+ coro.bind(thunk)
+ scheduler[0].add_new_thread(coro)
+ # XXX we should think about a way to make it read-only for the client
+ # aka true futures
+ return w_Future
+app_uthread = gateway.interp2app(uthread, unwrap_spec=[baseobjspace.ObjSpace,
+ baseobjspace.W_Root,
+ argument.Arguments])
+def initial_conditions(space):
+ scheduler[0]._check_initial_conditions()
+ w('success !')
+app_initial_conditions = gateway.interp2app(initial_conditions)
+
#-- VARIABLE ---------------------
class W_Var(W_Root, object):
@@ -171,37 +275,12 @@
return w_obj
def wait__Var(space, w_var):
- while 1:
- #print " :wait", w_var
- if space.is_true(space.is_free(w_var)):
- if not have_uthreads():
- raise OperationError(space.w_RuntimeError,
- space.wrap("trying to perform an operation on an unbound variable"))
- else:
- # notify wait_needed clients, give them a chance to run
- w_var.w_needed = True
- for w_alias in aliases(space, w_var):
- need_waiters = schedule_state.pop_blocked_byneed_on(w_alias)
- w_alias.w_needed = True
- for waiter in need_waiters:
- #print " :byneed waiter", waiter, "awaken on", w_alias
- schedule_state.add_to_runnable(waiter)
- # set curr thread to blocked, switch to runnable thread
- current = AppCoroutine.w_getcurrent(space)
- schedule_state.add_to_blocked(w_var, current)
- while schedule_state.have_runnable_threads():
- next_coro = schedule_state.pop_runnable_thread()
- if next_coro.is_alive():
- #print " :waiter is switching"
- next_coro.w_switch()
- #print " waiter is back"
- # hope there is a value here now
- break
- else:
- raise OperationError(space.w_RuntimeError,
- space.wrap("blocked on variable, but no uthread that can bind it"))
- else:
- return w_var.w_bound_to
+ #print " :wait", w_var
+ if space.is_true(space.is_free(w_var)):
+ scheduler[0].unblock_byneed_on(space, w_var)
+ scheduler[0].add_to_blocked_on(w_var, ClonableCoroutine.w_getcurrent(space))
+ scheduler[0].schedule()
+ return w_var.w_bound_to
def wait(space, w_obj):
assert isinstance(w_obj, W_Root)
@@ -215,34 +294,15 @@
def wait_needed__Var(space, w_var):
- while 1:
- #print " :needed", w_var
- if space.is_true(space.is_free(w_var)):
- if w_var.w_needed:
- break # we're done
- if not have_uthreads():
- raise OperationError(space.w_RuntimeError,
- space.wrap("oh please oh FIXME !"))
- else:
- # add current thread to blocked byneed and switch
- current = AppCoroutine.w_getcurrent(space)
- for w_alias in aliases(space, w_var):
- schedule_state.add_to_blocked_byneed(w_alias, current)
- while schedule_state.have_runnable_threads():
- next_coro = schedule_state.pop_runnable_thread()
- if next_coro.is_alive():
- #print " :needed is switching"
- next_coro.w_switch()
- #print " byneed is back"
- # there might be some need right now
- break
- else:
- raise OperationError(space.w_RuntimeError,
- space.wrap("blocked on need, but no uthread that can wait"))
-
- else:
- raise OperationError(space.w_RuntimeError,
- space.wrap("wait_needed only supported on unbound variables"))
+ #print " :needed", w_var
+ if space.is_true(space.is_free(w_var)):
+ if w_var.w_needed:
+ return
+ scheduler[0].add_to_blocked_byneed(w_var, ClonableCoroutine.w_getcurrent(space))
+ scheduler[0].schedule()
+ else:
+ raise OperationError(space.w_RuntimeError,
+ space.wrap("wait_needed only supported on unbound variables"))
def wait_needed(space, w_var):
assert isinstance(w_var, W_Var)
@@ -315,16 +375,6 @@
#-- HELPERS ----------------------
-## def disp(space, w_var):
-## print w_var
-## app_disp = gateway.interp2app(disp)
-
-## def disp_aliases(space, w_var):
-## print "Aliases of ", w_var, "are",
-## for w_al in aliases(space, w_var):
-## print w_al,
-## print
-
def deref(space, w_var):
"""gets the value of a bound variable
user has to ensure boundness of the var"""
@@ -364,43 +414,15 @@
raise OperationError(space.w_RuntimeError,
space.wrap("Unification failure"))
-def check_and_memoize_pair(space, w_x, w_y):
- pass
-
-def reset_memo():
- pass
def prettyfy_id(a_str):
- assert isinstance(a_str, W_StringObject)
+ assert isinstance(a_str, str)
l = len(a_str) - 1
return a_str[l-3:l]
-
-#FIXME : does not work at all,
-# even a pure applevel version ...
-## def _sleep(space, w_var, w_barrier):
-## assert isinstance(w_var, W_Var)
-## assert isinstance(w_barrier, W_Var)
-## wait(space, w_var)
-## bind(space, w_barrier, space.newint(1))
-
-## def wait_two(space, w_v1, w_v2):
-## """waits until one out of two logic variables
-## becomes bound, then tells which one,
-## with a bias toward the first if both are
-## suddenly bound"""
-## assert isinstance(w_v1, W_Var)
-## assert isinstance(w_v2, W_Var)
-## w_barrier = newvar(space)
-## uthread(space, space.wrap(_sleep),
-## argument.Arguments(space, [w_v1, w_barrier]))
-## uthread(space, space.wrap(_sleep),
-## argument.Arguments(space, [w_v2, w_barrier]))
-## wait(space, w_barrier)
-## if space.is_true(space.is_free(w_v2)):
-## return space.newint(1)
-## return space.newint(2)
-## app_wait_two = gateway.interp2app(wait_two)
+def interp_id(w_obj):
+ return space.newint(id(w_obj))
+app_interp_id = gateway.interp2app(interp_id)
#-- BIND -----------------------------
@@ -409,13 +431,14 @@
2. assign bound var to unbound var
3. assign value to unbound var
"""
- #print " :bind", w_var, w_obj
+ w(" :bind", LF=False)
assert isinstance(w_var, W_Var)
assert isinstance(w_obj, W_Root)
space.bind(w_var, w_obj)
app_bind = gateway.interp2app(bind)
def bind__Var_Var(space, w_v1, w_v2):
+ w("var var")
if space.is_true(space.is_bound(w_v1)):
if space.is_true(space.is_bound(w_v2)):
return unify(space, #FIXME: we could just raise
@@ -431,40 +454,39 @@
def bind__Var_Root(space, w_var, w_obj):
+ w("var val", id(w_var))
# 3. var and value
if space.is_true(space.is_free(w_var)):
return _assign(space, w_var, w_obj)
# for dataflow behaviour we should allow
# rebinding of unifiable values
+ if space.is_true(space.eq(w_var.w_bound_to, w_obj)):
+ return
raise OperationError(space.w_RuntimeError,
space.wrap("Cannot bind twice"))
-
bind_mm = StdObjSpaceMultiMethod('bind', 2)
bind_mm.register(bind__Var_Root, W_Var, W_Root)
bind_mm.register(bind__Var_Var, W_Var, W_Var)
all_mms['bind'] = bind_mm
def _assign(space, w_var, w_val):
+ w(" :assign")
assert isinstance(w_var, W_Var)
assert isinstance(w_val, W_Root)
- #print " :assign", w_var, w_val, '[',
w_curr = w_var
ass_count = 0
while 1:
w_next = w_curr.w_bound_to
w_curr.w_bound_to = w_val
- #print w_curr,
ass_count += 1
# notify the blocked threads
- to_awake = schedule_state.pop_blocked_on(w_curr)
- for thread in to_awake:
- schedule_state.add_to_runnable(thread)
+ scheduler[0].unblock_on(w_curr)
if space.is_true(space.is_nb_(w_next, w_var)):
break
# switch to next
w_curr = w_next
- #print "] (to", ass_count, "aliases)"
+ w(" :assigned")
return space.w_None
def _alias(space, w_v1, w_v2):
@@ -472,7 +494,7 @@
user must ensure freeness of both vars"""
assert isinstance(w_v1, W_Var)
assert isinstance(w_v2, W_Var)
- #print " :alias", w_v1, w_v2
+ w(" :alias", id(w_v1), id(w_v2))
if space.is_true(space.is_nb_(w_v1, w_v2)):
return space.w_None
if space.is_true(is_aliased(space, w_v1)):
@@ -489,7 +511,7 @@
def _add_to_aliases(space, w_v1, w_v2):
assert isinstance(w_v1, W_Var)
assert isinstance(w_v2, W_Var)
- #print " :add to aliases", w_v1, w_v2
+ w(" :add to aliases")
w_tail = w_v1.w_bound_to
w_v1.w_bound_to = w_v2
w_v2.w_bound_to = w_tail
@@ -498,7 +520,7 @@
def _merge_aliases(space, w_v1, w_v2):
assert isinstance(w_v1, W_Var)
assert isinstance(w_v2, W_Var)
- #print " :merge aliases", w_v1, w_v2
+ w(" :merge aliases")
w_tail1 = get_ring_tail(space, w_v1)
w_tail2 = get_ring_tail(space, w_v2)
w_tail1.w_bound_to = w_v2
@@ -510,7 +532,7 @@
def unify(space, w_x, w_y):
assert isinstance(w_x, W_Root)
assert isinstance(w_y, W_Root)
- #print ":unify ", w_x, w_y
+ #print ":unify ", id(w_x), id(w_y)
return space.unify(w_x, w_y)
app_unify = gateway.interp2app(unify)
@@ -525,7 +547,7 @@
return space.w_None
def unify__Var_Var(space, w_x, w_y):
- #print " :unify of two vars"
+ w(":unify var var", id(w_x), id(w_y))
if space.is_true(space.is_bound(w_x)):
if space.is_true(space.is_bound(w_y)):
return space.unify(deref(space, w_x),
@@ -536,7 +558,7 @@
return bind(space, w_x, w_y)
def unify__Var_Root(space, w_x, w_y):
- #print " :unify var and value"
+ w(" :unify var val", id(w_x))
if space.is_true(space.is_bound(w_x)):
return space.unify(deref(space, w_x), w_y)
return bind(space, w_x, w_y)
@@ -557,7 +579,6 @@
unify(space, w_xi, w_yi)
return space.w_None
-
def unify__List_List(space, w_i1, w_i2):
if len(w_i1.wrappeditems) != len(w_i2.wrappeditems):
fail(space, w_i1, w_i2)
@@ -570,11 +591,7 @@
continue
unify(space, w_xi, w_yi)
return space.w_None
-
-## def _unify_iterables(space, w_i1, w_i2):
-## assert isinstance(w_i1, W_TupleObject) or isinstance(w_i1, W_ListObject)
-## assert isinstance(w_i2, W_TupleObject) or isinstance(w_i2, W_ListObject)
-## #print " :unify iterables", w_i1, w_i2
+
def unify__Dict_Dict(space, w_m1, w_m2):
assert isinstance(w_m1, W_DictObject)
@@ -638,11 +655,14 @@
del setup
def eqproxy(space, parentfn):
+ """shortcuts wait filtering"""
def eq(w_obj1, w_obj2):
assert isinstance(w_obj1, W_Root)
assert isinstance(w_obj2, W_Root)
+ # check identity
if space.is_true(space.is_nb_(w_obj1, w_obj2)):
return space.newbool(True)
+ # check aliasing
if space.is_true(space.is_free(w_obj1)):
if space.is_true(space.is_free(w_obj2)):
if space.is_true(alias_of(space, w_obj1, w_obj2)):
@@ -772,8 +792,8 @@
setattr(space, name, boundmethod) # store into 'space' instance
# /multimethods hack
- # provide a UnificationError exception
- # XXX patching the table in-place? ARGH
+ # XXXprovide a UnificationError exception
+ # patching the table in-place?
#space.ExceptionTable.append('UnificationError')
#space.ExceptionTable.sort() # hmmm
@@ -799,7 +819,7 @@
space.wrap(domain.app_make_fd))
space.setitem(space.builtin.w_dict, space.wrap('intersection'),
space.wrap(domain.app_intersection))
- #-- contraint ----
+ #-- constraint ----
space.setitem(space.builtin.w_dict, space.wrap('make_expression'),
space.wrap(constraint.app_make_expression))
space.setitem(space.builtin.w_dict, space.wrap('AllDistinct'),
@@ -811,6 +831,22 @@
space.wrap(distributor.app_make_split_distributor))
space.setitem(space.builtin.w_dict, space.wrap('DichotomyDistributor'),
space.wrap(distributor.app_make_dichotomy_distributor))
+ #-- threading --
+ space.setitem(space.builtin.w_dict, space.wrap('uthread'),
+ space.wrap(app_uthread))
+ space.setitem(space.builtin.w_dict, space.wrap('wait'),
+ space.wrap(app_wait))
+ space.setitem(space.builtin.w_dict, space.wrap('wait_needed'),
+ space.wrap(app_wait_needed))
+
+ #-- misc -----
+ space.setitem(space.builtin.w_dict, space.wrap('initial_conditions'),
+ space.wrap(app_initial_conditions))
+ space.setitem(space.builtin.w_dict, space.wrap('initial_conditions'),
+ space.wrap(app_initial_conditions))
+ space.setitem(space.builtin.w_dict, space.wrap('interp_id'),
+ space.wrap(interp_id))
+
#-- path to the applevel modules --
import pypy.objspace.constraint
import os
@@ -818,36 +854,21 @@
dir = os.path.join(dir, 'applevel')
space.call_method(space.sys.get('path'), 'append', space.wrap(dir))
- if USE_COROUTINES:
- import os
- # make sure that _stackless is imported
- w_modules = space.getbuiltinmodule('_stackless')
- # xxx use the new startup/finish machinary for this
- def exitfunc():
- current = AppCoroutine.w_getcurrent(space)
- schedule_state.exhausting = 2
- while schedule_state.have_runnable_threads():
- next_coro = schedule_state.pop_runnable_thread()
- if next_coro.is_alive() and next_coro != current:
- schedule_state.add_to_runnable(current)
- next_coro.w_switch()
- schedule_state.remove_from_runnable(current)
- if schedule_state.have_blocked_threads():
- os.write(2, "there are still blocked uthreads!")
- app_exitfunc = gateway.interp2app(exitfunc, unwrap_spec=[])
-
- space.setitem(space.sys.w_dict, space.wrap("exitfunc"), space.wrap(app_exitfunc))
- space.setitem(space.builtin.w_dict, space.wrap('uthread'),
- space.wrap(app_uthread))
- space.setitem(space.builtin.w_dict, space.wrap('wait'),
- space.wrap(app_wait))
- space.setitem(space.builtin.w_dict, space.wrap('wait_needed'),
- space.wrap(app_wait_needed))
+ # make sure that _stackless is imported
+ w_modules = space.getbuiltinmodule('_stackless')
+ # cleanup func called from space.finish()
+ def exitfunc():
+ pass
+
+ app_exitfunc = gateway.interp2app(exitfunc, unwrap_spec=[])
+ space.setitem(space.sys.w_dict, space.wrap("exitfunc"), space.wrap(app_exitfunc))
- # capture a bunch of non-blocking ops
+ # capture one non-blocking op
space.is_nb_ = space.is_
-
- patch_space_in_place(space, 'logic', proxymaker)
- return space
+ # do the magic
+ patch_space_in_place(space, 'logic', proxymaker)
+ # instantiate singleton scheduler
+ scheduler.append(Scheduler(space))
+ return space
More information about the Pypy-commit
mailing list