git » pymisc » commit 06e48cb

Implement a semi-transparent dataflow decorator.

author Alberto Bertogli
2006-06-18 18:28:07 UTC
committer Alberto Bertogli
2006-06-18 18:28:07 UTC
parent 23eb152a88bf7cfdc31c7a5ce2adeb03c6b1257c

Implement a semi-transparent dataflow decorator.

dataflow.py +59 -0
samples/dataflow/sample2.py +21 -0

diff --git a/dataflow.py b/dataflow.py
index 6ab8f80..fe2c553 100644
--- a/dataflow.py
+++ b/dataflow.py
@@ -4,6 +4,7 @@ dataflow - Objects with dataflow semantics
 Alberto Bertogli (albertogli@telpin.com.ar)
 """
 
+import thread
 import threading
 
 class DFObject(object):
@@ -36,3 +37,61 @@ class DFObject(object):
 		self.__lock.release()
 
 
+class _DFWrapper:
+	"""Dataflow wrapper class for the decorator defined below.
+	It's closely related so don't use it.
+
+	We don't use a new-style class, otherwise we would have to implement
+	stub methods for __getattribute__, __hash__ and lots of others that
+	are inherited from object by default. This works too and is simple.
+	I'll deal with them when they become mandatory.
+	"""
+	def __init__(self):
+		self._override = True
+		self._isset = False
+		self._value = None
+		self._lock = threading.Condition()
+		self._override = False
+
+	def _wait(self):
+		self._lock.acquire()
+		while not self._isset:
+			self._lock.wait()
+		self._lock.release()
+
+	def __getattr__(self, name):
+		if self.__dict__['_override']:
+			return self.__dict__[name]
+		self._wait()
+		return getattr(self._value, name)
+
+	def __setattr__(self, name, val):
+		if name == '_override' or self._override:
+			self.__dict__[name] = val
+			return
+		self._wait()
+		setattr(self._value, name, val)
+		return
+
+def dataflow(f):
+	"Dataflow decorator"
+	obj = _DFWrapper()
+	def threadedf(*args, **kwargs):
+		v = f(*args, **kwargs)
+		obj._override = True
+		olock = obj._lock
+		olock.acquire()
+		obj._value = v
+		obj._isset = True
+		obj._wait = lambda: True
+		obj._override = False
+		olock.notifyAll()
+		olock.release()
+
+	def newf(*args, **kwargs):
+		thread.start_new_thread(threadedf, args, kwargs)
+		return obj
+
+	return newf
+
+
diff --git a/samples/dataflow/sample2.py b/samples/dataflow/sample2.py
new file mode 100644
index 0000000..7d95171
--- /dev/null
+++ b/samples/dataflow/sample2.py
@@ -0,0 +1,21 @@
+
+import dataflow
+import time
+
+
+def show(v):
+	print 'show() init + print'
+	print 'show() v: ' + str(v)
+	print 'show() done'
+
+@dataflow.dataflow
+def set():
+	print 'set() init + sleep'
+	time.sleep(1)
+	print 'set() returns 3'
+	return 3
+
+v = set()
+show(v)
+show(v)
+