Author: tmckay
Date: 2011-06-24 18:30:35 +0000 (Fri, 24 Jun 2011)
New Revision: 4856
Added:
branches/sage_addition/sage/python/sage/util.py
Log:
Forgot to add util.py on initial commit
Added: branches/sage_addition/sage/python/sage/util.py
===================================================================
--- branches/sage_addition/sage/python/sage/util.py (rev 0)
+++ branches/sage_addition/sage/python/sage/util.py 2011-06-24 18:30:35 UTC (rev 4856)
@@ -0,0 +1,84 @@
+from time import time, sleep
+
+class CallSync(object):
+ '''
+ General callback object for asynchronous operations.
+ The 'get_completion' method will return a function that can be
+ used as a callback when an asynchronous operation completes.
+ To change the signature of the callback function, derive from
+ this class and override 'get_completion', changing the definition
+ of the 'completion' function.
+ The 'done' method can be polled to determine if the operation has completed.
+ '''
+ def __init__(self, log=None, default=None):
+ self.data = default
+ self.got_data = False
+ self.error = False
+ self.status = None
+ self.log = log
+
+ def get_completion(self):
+ # Note that because of the way binding is done in Python,
+ # 'self' inside 'completion' is bound to 'obj' when
+ # obj.get_completion is called and 'completion' is returned.
+ # This allows the code invoking the callback to call a simple
+ # function without an object reference (the reference is hidden
+ # inside the bound function).
+ def completion(status, data):
+ self.status = status
+ if (status == 0) or (status == "OK"):
+ self.data = data
+ self.got_data = True
+ else:
+ self.error = Exception(status)
+ msg = "CallSync: call returned with status of %s" %
str(status)
+ if self.log is not None:
+ self.log.error(msg)
+ return completion
+
+ def done(self):
+ return self.got_data or self.error
+
+class SyncSet(object):
+ '''
+ Allows a caller to wait for completion of a set of asynchronous operations.
+ A collection of CallSync objects can be built up with calls to 'add_sync'.
+ 'do_wait' will return when all CallSync objects in the set have been
completed
+ or 'timeout' seconds have elapsed.
+ '''
+ def __init__(self, log=None, timeout=5):
+ self.syncs = dict()
+ self.timeout = timeout
+ self.log = log
+
+ def add_sync(self, key, default=None):
+ sync = CallSync(self.log, default)
+ self.syncs[key] = sync
+ return sync
+
+ def do_wait(self):
+ def predicate(syncs):
+ done = 0
+ for k, sync in syncs.items():
+ if sync.done():
+ done += 1
+ return done == len(syncs)
+
+ # Wait for all syncs in the set to complete.
+ # syncs will contain results for each call passed back
+ # through the completion callback
+ wait(predicate, timeout=self.timeout, args=self.syncs)
+ return self.syncs
+
+def wait(predicate, timeout=30, args=None):
+ start = time()
+ while True:
+ if args is not None:
+ if predicate(args):
+ return True
+ else:
+ if predicate():
+ return True
+ if time() - start > timeout:
+ return False
+ sleep(1)
Show replies by thread