|
1 import threading # Only used in SetupEvent |
|
2 |
|
3 class _Callback(object): |
|
4 def __init__(self, callback, errorback, threaded = False): |
|
5 self.callback = callback |
|
6 self.errorback = errorback |
|
7 self.next = None |
|
8 self.threaded = threaded |
|
9 def Chain(self, next): |
|
10 # Can only be called once |
|
11 assert(self.next is None) |
|
12 self.next = next |
|
13 return next |
|
14 def Next(self): |
|
15 return self.next |
|
16 |
|
17 ## |
|
18 # A task, representing a series of linked pairs of callback and error |
|
19 # handler Concept is similar to twisted, but you need to put all your |
|
20 # callback on the task before giving it to the Scheduler. For this |
|
21 # reason, you shouldnt call the callback/errorback method yourself (or |
|
22 # at least, don't put it back in the scheduler after that). |
|
23 |
|
24 class Task(object): |
|
25 |
|
26 @staticmethod |
|
27 def DefaultCallback(result): |
|
28 return result |
|
29 |
|
30 @staticmethod |
|
31 def DefaultErrorback(error): |
|
32 return error |
|
33 |
|
34 def __init__(self, func = None, *args, **kwargs): |
|
35 super(Task, self).__init__() |
|
36 self.head = None |
|
37 self.tail = None |
|
38 if func: |
|
39 def callback(result): |
|
40 return func(*args, **kwargs) |
|
41 self.AddCallback(callback) |
|
42 |
|
43 def _AddCallback(self, callback): |
|
44 if self.head is None: |
|
45 self.head = self.tail = callback |
|
46 else: |
|
47 self.tail = self.tail.Chain(callback) |
|
48 |
|
49 def _GetNext(self): |
|
50 head = self.head |
|
51 if head: |
|
52 self.head = head.Next() |
|
53 return head |
|
54 |
|
55 def AddCallback(self, callback, errorback = None, threaded = False): |
|
56 if errorback == None: |
|
57 errorback = self.DefaultErrorback |
|
58 cb = _Callback(callback, errorback, threaded) |
|
59 self._AddCallback(cb) |
|
60 # permit chained calls |
|
61 return self |
|
62 |
|
63 def AddThreadedCallback(self, callback, errorback = None): |
|
64 return self.AddCallback(callback, errorback, True) |
|
65 |
|
66 def ChainTask(self, task): |
|
67 self.tail.Chain(task.head) |
|
68 self.tail = task.tail |
|
69 |
|
70 def GrabResult(self, data = None): |
|
71 if data is None: |
|
72 data = {} |
|
73 def SetResult(result): |
|
74 data["result"] = result |
|
75 return result |
|
76 def SetError(error): |
|
77 data["error"] = error |
|
78 self.AddCallback(SetResult, SetError) |
|
79 return data |
|
80 |
|
81 def SetupEvent(self, event = None, data = None): |
|
82 if not event: |
|
83 event = threading.Event() |
|
84 def SetEvent(dummy): |
|
85 event.set() |
|
86 self.AddCallback(SetEvent, SetEvent) |
|
87 return event |
|
88 |
|
89 ## |
|
90 # Helper class |
|
91 class ThreadedTask(Task): |
|
92 def __init__(self, func, *args, **kwargs): |
|
93 super(ThreadedTask, self).__init__(func, *args, **kwargs) |
|
94 self.head.threaded = True |
|
95 |