[pypy-svn] r23905 - pypy/dist/pypy/lib/logic/computation_space

auc at codespeak.net auc at codespeak.net
Thu Mar 2 14:08:27 CET 2006


Author: auc
Date: Thu Mar  2 14:08:25 2006
New Revision: 23905

Modified:
   pypy/dist/pypy/lib/logic/computation_space/computationspace.py
   pypy/dist/pypy/lib/logic/computation_space/distributor.py
   pypy/dist/pypy/lib/logic/computation_space/test_variable.py
   pypy/dist/pypy/lib/logic/computation_space/variable.py
Log:
introduce spaceless variables
use them for space impl. purposes


Modified: pypy/dist/pypy/lib/logic/computation_space/computationspace.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/computationspace.py	(original)
+++ pypy/dist/pypy/lib/logic/computation_space/computationspace.py	Thu Mar  2 14:08:25 2006
@@ -11,8 +11,9 @@
 from state import Succeeded, Distributable, Failed, \
      Unknown, Forsaken
 
-from variable import EqSet, Var, NoValue, NoDom, \
-     VariableException, NotAVariable, AlreadyInStore
+from variable import EqSet, CsVar, NoValue, NoDom, \
+     VariableException, NotAVariable, AlreadyInStore, \
+     AlreadyBound, SimpleVar
 from constraint import FiniteDomain, ConsistencyFailure, \
      Expression
 from distributor import DefaultDistributor
@@ -144,8 +145,8 @@
         self.distributor = None
         self.parent = None
         self.children = None
-        self.CHOOSE.bind(0)
-        self.STABLE.bind(0)
+        self.CHOOSE.bind(True)
+        self.STABLE.bind(True)
 
     def __eq__(self, spc):
         """space equality defined as :
@@ -196,15 +197,12 @@
     #-- space helpers -----------------------------------------
 
     def _make_choice_var(self):
-        ComputationSpace._nb_choices += 1
-        ch_var = self.var('__choice__'+str(self._nb_choices))
-        return ch_var
+        return SimpleVar()
 
     def _make_stable_var(self):
-        ComputationSpace._nb_choices += 1
-        st_var = self.var('__stable__'+str(self._nb_choices))
-        return st_var
+        return SimpleVar()
 
+    
     def _process(self):
         """wraps the propagator"""
         if len(self.event_set):
@@ -268,10 +266,8 @@
         """
         # did you ask before ... ?
         assert self.STABLE.is_bound()
-        old_stable_var = self.STABLE
         self.STABLE = self._make_stable_var()
-        self._del_var(old_stable_var)
-        self.bind(self.CHOOSE, choice)
+        self.CHOOSE.bind(choice)
 
     def choose(self, nb_choices):
         """
@@ -293,7 +289,7 @@
         #for var in self.root.val:
         #    var.bind(self.dom(var).get_values()[0])
         # shut down the distributor
-        self.CHOOSE.bind(0)
+        self.CHOOSE.bind(True)
         res = []
         for var in self.root.val:
             res.append(self.dom(var).get_values()[0])
@@ -311,7 +307,7 @@
            and puts it into the store"""
         self.var_lock.acquire()
         try:
-            v = Var(name, self)
+            v = CsVar(name, self)
             self.add_unbound(v)
             return v
         finally:
@@ -372,14 +368,14 @@
 
     def set_dom(self, var, dom):
         """bind variable to domain"""
-        assert(isinstance(var, Var) and (var in self.vars))
+        assert(isinstance(var, CsVar) and (var in self.vars))
         if var.is_bound():
             print "warning : setting domain %s to bound var %s" \
                   % (dom, var)
         self.doms[var] = FiniteDomain(dom)
 
     def dom(self, var):
-        assert isinstance(var, Var)
+        assert isinstance(var, CsVar)
         try:
             return self.doms[var]
         except KeyError:
@@ -596,7 +592,7 @@
         # removed (this last condition remains to be checked)
         self.bind_lock.acquire()
         try:
-            assert(isinstance(var, Var) and (var in self.vars))
+            assert(isinstance(var, CsVar) and (var in self.vars))
             if var == val:
                 return
             if _both_are_vars(var, val):
@@ -745,7 +741,7 @@
         return False
     if _mapping(term1) and _mapping(term2):
         return _mapping_unifiable(term1, term2)
-    if not(isinstance(term1, Var) or isinstance(term2, Var)):
+    if not(isinstance(term1, CsVar) or isinstance(term2, CsVar)):
         return term1 == term2 # same 'atomic' object
     return True
         
@@ -774,7 +770,7 @@
 #-- Some utilities -------------------------------------------
 
 def _both_are_vars(v1, v2):
-    return isinstance(v1, Var) and isinstance(v2, Var)
+    return isinstance(v1, CsVar) and isinstance(v2, CsVar)
     
 def _both_are_bound(v1, v2):
     return v1._is_bound() and v2._is_bound()

Modified: pypy/dist/pypy/lib/logic/computation_space/distributor.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/distributor.py	(original)
+++ pypy/dist/pypy/lib/logic/computation_space/distributor.py	Thu Mar  2 14:08:25 2006
@@ -153,12 +153,9 @@
             print "-- distribution & propagation (%s) --" % self.cs.id
             self.distribute(choice-1)
             self.cs._process()
-            old_choose_var = self.cs.CHOOSE
             self.cs.CHOOSE = self.cs._make_choice_var()
-            self.cs._del_var(old_choose_var)
             self.cs.STABLE.bind(True) # unlocks Ask
         print "-- distributor terminated (%s) --" % self.cs.id
-        self.cs.STABLE.bind(True) # it can't hurt ...
 
 
     def distribute(self, choice):

Modified: pypy/dist/pypy/lib/logic/computation_space/test_variable.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/test_variable.py	(original)
+++ pypy/dist/pypy/lib/logic/computation_space/test_variable.py	Thu Mar  2 14:08:25 2006
@@ -41,7 +41,34 @@
 
 #-- meat ----------------------------
 
-class TestVariable:
+class TestSimpleVariable:
+
+    def test_basics(self):
+        x = v.SimpleVar()
+        assert x.val == v.NoValue
+        x.bind(42)
+        assert x.val == 42
+        x.bind(42)
+        raises(v.AlreadyBound, x.bind, 43)
+
+    def test_dataflow(self):
+        def fun(thread, var):
+            thread.state = 1
+            v = var.get()
+            thread.state = v
+
+        x = v.SimpleVar()
+        t = FunThread(fun, x)
+        import time
+        t.start()
+        time.sleep(.5)
+        assert t.state == 1
+        x.bind(42)
+        t.join()
+        assert t.state == 42
+            
+
+class TestCsVariable:
 
     def test_no_same_name(self):
         sp = newspace()

Modified: pypy/dist/pypy/lib/logic/computation_space/variable.py
==============================================================================
--- pypy/dist/pypy/lib/logic/computation_space/variable.py	(original)
+++ pypy/dist/pypy/lib/logic/computation_space/variable.py	Thu Mar  2 14:08:25 2006
@@ -9,9 +9,15 @@
     def __str__(self):
         return "%s already in store" % self.name
 
-class AlreadyBound(VariableException):
+class AlreadyBound(Exception):
+    def __init__(self, var, val):
+        self.var = var
+        self.val = val
+    
     def __str__(self):
-        return "%s is already bound" % self.name
+        return "%s:%s already bound to %s" % (self.var.name,
+                                              self.var.val,
+                                              self.val)
 
 class NotAVariable(VariableException):
     def __str__(self):
@@ -25,16 +31,25 @@
 class NoDom: pass
 
 class SimpleVar(object):
-    def __init__(self, name):
-        self.name = name
+    """Spaceless dataflow variable"""
+    
+    def __init__(self):
+        self.name = str(id(self))
         self._val = NoValue
         # a condition variable for concurrent access
         self._value_condition = threading.Condition()
 
     # value accessors
     def _set_val(self, val):
-        if val != NoValue:
-            raise AlreadyBound(self.name)
+        self._value_condition.acquire()
+        try:
+            if self._val != NoValue:
+                if val != self._val:
+                    raise AlreadyBound(self, val)
+            self._val = val
+            self._value_condition.notifyAll()
+        finally:
+            self._value_condition.release()
         
     def _get_val(self):
         return self._val
@@ -60,14 +75,14 @@
         """
         try:
             self._value_condition.acquire()
-            while not self._is_bound():
+            while not self.is_bound():
                 self._value_condition.wait()
             return self.val
         finally:
             self._value_condition.release()
 
 
-class Var(SimpleVar):
+class CsVar(SimpleVar):
     """Dataflow variable linked to a space"""
 
     def __init__(self, name, cs):
@@ -103,13 +118,15 @@
     # value accessors
     def _set_val(self, val):
         self._value_condition.acquire()
-        if self._cs.in_transaction:
-            if not self._changed:
-                self._previous = self._val
-                self._changed = True
-        self._val = val
-        self._value_condition.notifyAll()
-        self._value_condition.release()
+        try:
+            if self._cs.in_transaction:
+                if not self._changed:
+                    self._previous = self._val
+                    self._changed = True
+            self._val = val
+            self._value_condition.notifyAll()
+        finally:
+            self._value_condition.release()
         
     def _get_val(self):
         return self._val
@@ -124,7 +141,7 @@
         return self.__str__()
 
     def __eq__(self, thing):
-        return isinstance(thing, Var) \
+        return isinstance(thing, self.__class__) \
                and self.name == thing.name
 
     def bind(self, val):



More information about the Pypy-commit mailing list