[pypy-svn] r35875 - in pypy/dist/pypy/objspace: cclp cclp/constraint test

auc at codespeak.net auc at codespeak.net
Tue Dec 19 10:40:37 CET 2006


Author: auc
Date: Tue Dec 19 10:40:32 2006
New Revision: 35875

Modified:
   pypy/dist/pypy/objspace/cclp/constraint/domain.py
   pypy/dist/pypy/objspace/cclp/scheduler.py
   pypy/dist/pypy/objspace/cclp/space.py
   pypy/dist/pypy/objspace/cclp/thunk.py
   pypy/dist/pypy/objspace/cclp/types.py
   pypy/dist/pypy/objspace/test/test_logicobjspace.py
Log:
current state of the (non-cloning) cloning stuff, better error checking bits wrt applevel


Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/constraint/domain.py	(original)
+++ pypy/dist/pypy/objspace/cclp/constraint/domain.py	Tue Dec 19 10:40:32 2006
@@ -138,8 +138,6 @@
 
 
 def intersection(space, w_fd1, w_fd2):
-    assert isinstance(w_fd1, W_FiniteDomain)
-    assert isinstance(w_fd2, W_FiniteDomain)
     return space.intersection(w_fd1, w_fd2)
 app_intersection = gateway.interp2app(intersection)
 

Modified: pypy/dist/pypy/objspace/cclp/scheduler.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/scheduler.py	(original)
+++ pypy/dist/pypy/objspace/cclp/scheduler.py	Tue Dec 19 10:40:32 2006
@@ -41,11 +41,18 @@
         group._prev = l
         group._next = r
 
+
     def schedule(self):
+        running = self._head
         to_be_run = self._select_next()
         assert isinstance(to_be_run, W_ThreadGroupScheduler), "type error"
         #w(".. SWITCHING (spaces)", str(id(get_current_cspace(self.space))), "=>", str(id(to_be_run)))
         self._switch_count += 1
+        if to_be_run != running:
+            if running._pool is not None:
+                running.goodbye()
+            if to_be_run._pool is not None:
+                to_be_run.hello()
         to_be_run.schedule() 
 
     def _select_next(self):
@@ -230,10 +237,12 @@
 
 #-- Thread Group scheduler --------------------------------------
 
+
 class W_ThreadGroupScheduler(baseobjspace.Wrappable):
 
     def __init__(self, space):
         self.space = space
+        self._pool = None
         self._switch_count = 0
         self._traced = {} # thread -> vars
         self.thread_count = 1
@@ -259,6 +268,18 @@
         thread._prev = l
         thread._next = r
 
+    def hello(self):
+        self._pool.hello_local_pool()
+
+    def goodbye(self):
+        self._pool.goodbye_local_pool()
+
+    def register_var(self, var):
+        space = self.space
+        raise OperationError(space.w_AssertionError,
+                             space.wrap('You cannot create a constraint variable '
+                                        'in the top-level computation space.'))
+
     def is_blocked(self):
         return self.thread_count == self.blocked_count
 

Modified: pypy/dist/pypy/objspace/cclp/space.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/space.py	(original)
+++ pypy/dist/pypy/objspace/cclp/space.py	Tue Dec 19 10:40:32 2006
@@ -15,13 +15,11 @@
 from pypy.objspace.cclp.global_state import sched
 from pypy.objspace.cclp.variable import newvar
 from pypy.objspace.cclp.types import ConsistencyError, Solution, W_Var, \
-     W_CVar, W_AbstractDomain, W_AbstractDistributor
+     W_CVar, W_AbstractDomain, W_AbstractDistributor, Pool
 from pypy.objspace.cclp.interp_var import interp_bind, interp_free
 from pypy.objspace.cclp.constraint.distributor import distribute
 from pypy.objspace.cclp.scheduler import W_ThreadGroupScheduler
 
-from pypy.rlib.rgc import gc_swap_pool, gc_clone
-
 def newspace(space, w_callable, __args__):
     "application level creation of a new computation space"
     args = __args__.normalize()
@@ -39,81 +37,66 @@
 
 
 def choose(space, w_n):
-    assert isinstance(w_n, W_IntObject)
+    if not isinstance(w_n, W_IntObject):
+        raise OperationError(space.w_TypeError,
+                             space.wrap('Choose only accepts an integer.'))
     n = space.int_w(w_n)
+    # XXX sanity check for 1 <= n <= last_choice
     cspace = get_current_cspace(space)
-    if cspace is not None:
-        assert isinstance(cspace, W_CSpace)
-        try:
-            return cspace.choose(w_n.intval)
-        except ConsistencyError:
-            raise OperationError(space.w_ConsistencyError,
-                                 space.wrap("the space is failed"))
-    raise OperationError(space.w_RuntimeError,
-                         space.wrap("choose is forbidden from the top-level space"))
+    if not isinstance(cspace, W_CSpace):
+        raise OperationError(space.w_TypeError,
+                             space.wrap('Choose does not work from within '
+                                        'the top-level computatoin space.'))
+    try:
+        return cspace.choose(n)
+    except ConsistencyError:
+        raise OperationError(space.w_ConsistencyError,
+                             space.wrap("the space is failed"))
 app_choose = gateway.interp2app(choose)
 
-
 from pypy.objspace.cclp.constraint import constraint
 
 def tell(space, w_constraint):
-    assert isinstance(w_constraint, constraint.W_AbstractConstraint)
+    if not isinstance(w_constraint, constraint.W_AbstractConstraint):
+        raise OperationError(space.w_TypeError,
+                             space.wrap('Tell only accepts object of '
+                                        '(sub-)types Constraint.'))
     get_current_cspace(space).tell(w_constraint)
 app_tell = gateway.interp2app(tell)
 
-if not we_are_translated():
-    def fresh_distributor(space, w_dist):
-        cspace = w_dist._cspace
-        while w_dist.distributable():
-            choice = cspace.choose(w_dist.fanout())
-            w_dist.w_distribute(choice)
-    app_fresh_distributor = gateway.interp2app(fresh_distributor)
-
 
 class W_CSpace(W_ThreadGroupScheduler):
-    local_pool = None
 
     def __init__(self, space, dist_thread):
         W_ThreadGroupScheduler.__init__(self, space)
         dist_thread._cspace = self
         self._init_head(dist_thread)
         self._next = self._prev = self
+        self._pool = Pool(self)
         sched.uler.add_new_group(self)
-
         self.distributor = None # dist instance != thread
-        self._container = None # thread that 'contains' us
         # choice mgmt
         self._choice = newvar(space)
         self._committed = newvar(space)
         # status, merging
         self._solution = newvar(space)
-        self._finished = newvar(space)
         self._failed = False
+        self._merged = False
+        self._finished = newvar(space)
         # constraint store ...
         self._store = {} # name -> var
-        if not we_are_translated():
-            self._constraints = []
         
     def register_var(self, cvar):
         self._store[cvar.name] = cvar
 
     def w_clone(self):
-        if we_are_translated():
-            w("<> cloning the space")
-            if self.local_pool is None:
-                self.local_pool = gc_swap_pool(gc_swap_pool(None))
-            new_cspace, new_cspace.local_pool = gc_clone(self, self.local_pool)
-            w("<> add cloned cspace to new group")
-            assert isinstance(new_cspace, W_CSpace)
-            new_cspace._next = new_cspace._prev = new_cspace
-            sched.uler.add_new_group(new_cspace)
-            w("<> returning clone ")
-            return new_cspace
-        else:
-            raise NotImplementedError
-
+        clone = self._pool.clone()
+        return self.space.wrap(clone.cspace)
 
     def w_ask(self):
+        if not interp_free(self._finished):
+            raise OperationError(self.space.w_RuntimeError,
+                                 self.space.wrap("space is finished"))
         self.wait_stable()
         self.space.wait(self._choice)
         choice = self._choice.w_bound_to
@@ -123,6 +106,9 @@
         return choice
 
     def choose(self, n):
+        if not interp_free(self._finished):
+            raise OperationError(self.space.w_RuntimeError,
+                                 self.space.wrap("space is finished"))
         # solver probably asks
         assert n > 1
         self.wait_stable()
@@ -138,6 +124,9 @@
         return committed
 
     def w_commit(self, w_n):
+        if not interp_free(self._finished):
+            raise OperationError(self.space.w_RuntimeError,
+                                 self.space.wrap("space is finished"))
         assert isinstance(w_n, W_IntObject)
         n = w_n.intval
         assert interp_free(self._committed)
@@ -152,9 +141,6 @@
         w_coro._cspace = self
         thunk = PropagatorThunk(space, w_constraint, w_coro)
         w_coro.bind(thunk)
-        if not we_are_translated():
-            w("PROPAGATOR in thread", str(id(w_coro)))
-            self._constraints.append(w_constraint)
         self.add_new_thread(w_coro)
 
     def fail(self):
@@ -167,6 +153,10 @@
 
     def w_merge(self):
         # let's bind the solution variables
+        if self._merged:
+            raise OperationError(self.space.w_RuntimeError,
+                                 self.space.wrap("space is already merged"))
+        self._merged = True
         sol = self._solution.w_bound_to
         if isinstance(sol, W_ListObject):
             self._bind_solution_variables(sol.wrappeditems)
@@ -191,10 +181,7 @@
 
 
 def contains_cvar(lst):
-    for elt in lst:
-        if isinstance(elt, W_CVar):
-            return True
-    return False
+    return isinstance(lst[0], W_CVar)
 
 
 W_CSpace.typedef = typedef.TypeDef("W_CSpace",

Modified: pypy/dist/pypy/objspace/cclp/thunk.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/thunk.py	(original)
+++ pypy/dist/pypy/objspace/cclp/thunk.py	Tue Dec 19 10:40:32 2006
@@ -108,7 +108,7 @@
                 outcome = sol.w_bound_to
                 if not (isinstance(outcome, W_ListObject) or \
                         isinstance(outcome, W_TupleObject)):
-                    w("WARNING: return value type of the script was not a list or tuple, we fail ...")
+                    w("WARNING: return value type of the script was not a list or tuple, we fail the space.")
                     cspace.fail()
                     return
                 assert interp_free(cspace._choice)

Modified: pypy/dist/pypy/objspace/cclp/types.py
==============================================================================
--- pypy/dist/pypy/objspace/cclp/types.py	(original)
+++ pypy/dist/pypy/objspace/cclp/types.py	Tue Dec 19 10:40:32 2006
@@ -2,6 +2,10 @@
 from pypy.interpreter.error import OperationError
 
 from pypy.objspace.cclp.misc import w, AppCoroutine, get_current_cspace
+from pypy.objspace.cclp.global_state import sched
+
+from pypy.rlib.rgc import gc_swap_pool, gc_clone
+from pypy.rlib.objectmodel import we_are_translated
 
 W_Root = baseobjspace.W_Root
 
@@ -42,11 +46,7 @@
         self.w_dom = w_dom
         self.name = space.str_w(w_name)
         self.w_nam = w_name
-        cspace = get_current_cspace(space)
-        if cspace is None:
-            w("-- WARNING : you are instanciating a constraint var in the top-level space")
-        else:
-            cspace.register_var(self)
+        get_current_cspace(space).register_var(self)
 
     def copy(self, space):
         return W_CVar(space, self.w_dom.copy(), self.w_nam)
@@ -124,6 +124,49 @@
 
 W_AbstractDistributor.typedef = typedef.TypeDef("W_AbstractDistributor")
 
+#-- Pool --------------------------------------------------
+
+class Pool:
+    local_pool = None
+
+    def __init__(self, cspace=None):
+        self.cspace = cspace
+
+    def hello_local_pool(self):
+        if we_are_translated():
+            w('hello_local_pool')
+            self.saved_pool = gc_swap_pool(self.local_pool)
+
+    def goodbye_local_pool(self):
+        if we_are_translated():
+            w('goodbye_local_pool')
+            self.local_pool = gc_swap_pool(self.saved_pool)
+            self.saved_pool = None
+
+    def clone(self):
+        copy = Pool()
+        self.clone_into(copy)
+        return copy
+
+    def clone_into(self, copy, extradata=None):
+        # blindly copied from interp_clonable
+        # all we need is love, after all ...
+        if not we_are_translated():
+            raise NotImplementedError
+        # cannot gc_clone() directly self, because it is not in its own
+        # local_pool.  Moreover, it has a __del__, which cloning doesn't
+        # support properly at the moment.
+        # the hello/goodbye pair has two purposes: it forces
+        # self.local_pool to be computed even if it was None up to now,
+        # and it puts the 'data' tuple in the correct pool to be cloned.
+        self.hello_local_pool()
+        data = (self.cspace, extradata)
+        self.goodbye_local_pool()
+        # clone!
+        data, copy.local_pool = gc_clone(data, self.local_pool)
+        copy.cspace, extradata = data
+        return extradata
+
 
 #-- Misc ---------------------------------------------------
 

Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_logicobjspace.py	(original)
+++ pypy/dist/pypy/objspace/test/test_logicobjspace.py	Tue Dec 19 10:40:32 2006
@@ -764,6 +764,7 @@
                     break
             if status:
                 unify(Sol, spc.merge())
+                raises(AssertionError, spc.merge)
             else:
                 unify(Sol, False)
 



More information about the Pypy-commit mailing list