1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """A threaded version of the relax interpreter for use by the GUI."""
25
26
27 from Queue import Queue
28 from re import search
29 from string import split
30 import sys
31 from threading import Thread
32 from time import sleep
33 from traceback import print_exc
34 import wx
35
36
37 from prompt import interpreter
38 from relax_errors import AllRelaxErrors
39 from status import Status; status = Status()
40
41
42 from gui.errors import gui_raise
43
44
46 """The threaded interpreter."""
47
48
49 _instance = None
50
73
74
76 """Return the user function object corresponding to the given string.
77
78 @param uf: The name of the user function.
79 @type uf: str
80 @return: The user function object.
81 @rtype: func
82 """
83
84
85 if search('\.', uf):
86
87 uf_class, uf_fn = split(uf, '.')
88
89
90 obj = getattr(self._interpreter, uf_class)
91
92
93 fn = getattr(obj, uf_fn)
94
95
96 else:
97 fn = getattr(self._interpreter, uf)
98
99
100 return fn
101
102
103 - def apply(self, uf, *args, **kwds):
104 """Apply a user function for synchronous execution.
105
106 @param uf: The user function as a string.
107 @type uf: str
108 @param args: The user function arguments.
109 @type args: any arguments
110 @param kwds: The user function keyword arguments.
111 @type kwds: any keyword arguments
112 @return: Whether the user function was successfully applied or not.
113 @rtype: bool
114 """
115
116
117 if status.debug:
118 sys.stdout.write("debug> GUI interpreter: Applying the %s user function for synchronous execution.\n" % uf)
119
120
121 fn = self._get_uf(uf)
122
123
124 try:
125 apply(fn, args, kwds)
126
127
128 except AllRelaxErrors, instance:
129
130 gui_raise(instance, raise_flag=False)
131
132
133 return False
134
135
136 status.observers.gui_uf.notify()
137
138
139 return True
140
141
143 """Determine if the interpreter thread queue is empty.
144
145 This is a wrapper method for the thread method.
146 """
147
148
149 return self._interpreter_thread.empty()
150
151
153 """Cause the thread to exit once all currently queued user functions are processed.
154
155 This is a wrapper method for the thread method.
156 """
157
158
159 return self._interpreter_thread.exit()
160
161
163 """Return only once the queue is empty.
164
165 This is a wrapper method for the interpreter thread.
166 """
167
168
169 if status.debug:
170 sys.stdout.write("debug> GUI interpreter: Flushing.\n")
171
172
173 sleep(0.5)
174
175
176 while not self._interpreter_thread.empty():
177
178 sleep(0.2)
179
180
181 while status.exec_lock.locked():
182 sleep(0.5)
183
184
185 if status.debug:
186 sys.stdout.write("debug> GUI interpreter: Flushed.\n")
187
188
190 """Wrapper method for the Queue.join() method."""
191
192
193 self._interpreter_thread.join()
194
195
196 - def queue(self, uf, *args, **kwds):
197 """Queue up a user function.
198
199 This is a wrapper method for the interpreter thread.
200
201 @param uf: The user function as a string.
202 @type uf: str
203 @param args: The user function arguments.
204 @type args: any arguments
205 @param kwds: The user function keyword arguments.
206 @type kwds: any keyword arguments
207 """
208
209
210 if status.debug:
211 sys.stdout.write("debug> GUI interpreter: Queuing the %s user function for asynchronous execution.\n" % uf)
212
213
214 fn = self._get_uf(uf)
215
216
217 self._interpreter_thread.queue(fn, *args, **kwds)
218
219
220
222 """The threaded interpreter."""
223
225 """Initialise the object."""
226
227
228 Thread.__init__(self)
229
230
231 self.daemon = True
232
233
234 self._queue = Queue()
235
236
237 self._uf_list = []
238
239
240 self._exit = False
241
242
244 """Is the queue empty?"""
245
246
247 if status.exec_lock.locked():
248 return False
249
250
251 elif len(self._uf_list):
252 return False
253
254
255 else:
256 return True
257
258
260 """Cause the thread to exit once all currently queued user functions are processed."""
261
262
263 self._exit = True
264
265
266 self._queue.put([None, None, None])
267
268
270 """Wrapper method for the Queue.join() method."""
271
272
273 self._queue.join()
274
275
276 - def queue(self, fn, *args, **kwds):
277 """Queue up a user function for asynchronous execution.
278
279 @param fn: The user function as a string.
280 @type fn: str
281 @param args: The user function arguments.
282 @type args: any arguments
283 @param kwds: The user function keyword arguments.
284 @type kwds: any keyword arguments
285 """
286
287
288 self._uf_list.append(repr(fn))
289
290
291 self._queue.put([fn, args, kwds])
292
293
295 """Execute the thread."""
296
297
298 while not self._exit:
299
300 fn, args, kwds = self._queue.get()
301
302
303 if fn == None:
304 continue
305
306
307 status.exec_lock.acquire('gui', mode='interpreter thread')
308
309
310 try:
311 apply(fn, args, kwds)
312
313
314 except AllRelaxErrors, instance:
315
316 wx.CallAfter(gui_raise, instance, raise_flag=False)
317
318
319 except:
320
321 print_exc()
322
323
324 finally:
325
326 self._queue.task_done()
327
328
329 status.exec_lock.release()
330
331
332 self._uf_list.pop(self._uf_list.index(repr(fn)))
333
334
335 status.observers.gui_uf.notify()
336