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 from user_functions.data import Uf_info; uf_info = Uf_info()
41
42
43 from gui.errors import gui_raise
44
45
47 """The threaded interpreter."""
48
49
50 _instance = None
51
74
75
77 """Return the user function object corresponding to the given string.
78
79 @param uf: The name of the user function.
80 @type uf: str
81 @return: The user function object.
82 @rtype: func
83 """
84
85
86 info = uf_info.get_uf(uf)
87
88
89 return info.backend
90
91
92 - def apply(self, uf, *args, **kwds):
93 """Apply a user function for synchronous execution.
94
95 @param uf: The user function as a string.
96 @type uf: str
97 @param args: The user function arguments.
98 @type args: any arguments
99 @param kwds: The user function keyword arguments.
100 @type kwds: any keyword arguments
101 @return: Whether the user function was successfully applied or not.
102 @rtype: bool
103 """
104
105
106 if status.debug:
107 sys.stdout.write("debug> GUI interpreter: Applying the %s user function for synchronous execution.\n" % uf)
108
109
110 fn = self._get_backend(uf)
111
112
113 try:
114 apply(fn, args, kwds)
115
116
117 except AllRelaxErrors, instance:
118
119 gui_raise(instance, raise_flag=False)
120
121
122 return False
123
124
125 status.observers.gui_uf.notify()
126
127
128 return True
129
130
132 """Determine if the interpreter thread queue is empty.
133
134 This is a wrapper method for the thread method.
135 """
136
137
138 return self._interpreter_thread.empty()
139
140
142 """Cause the thread to exit once all currently queued user functions are processed.
143
144 This is a wrapper method for the thread method.
145 """
146
147
148 return self._interpreter_thread.exit()
149
150
152 """Return only once the queue is empty.
153
154 This is a wrapper method for the interpreter thread.
155 """
156
157
158 if status.debug:
159 sys.stdout.write("debug> GUI interpreter: Flushing.\n")
160
161
162 sleep(0.05)
163
164
165 while not self._interpreter_thread.empty():
166
167 sleep(0.05)
168
169
170 while status.exec_lock.locked():
171 sleep(0.1)
172
173
174 if status.debug:
175 sys.stdout.write("debug> GUI interpreter: Flushed.\n")
176
177
179 """Wrapper method for the Queue.join() method."""
180
181
182 self._interpreter_thread.join()
183
184
185 - def queue(self, uf, *args, **kwds):
186 """Queue up a user function.
187
188 This is a wrapper method for the interpreter thread.
189
190 @param uf: The user function as a string.
191 @type uf: str
192 @param args: The user function arguments.
193 @type args: any arguments
194 @param kwds: The user function keyword arguments.
195 @type kwds: any keyword arguments
196 """
197
198
199 if status.debug:
200 sys.stdout.write("debug> GUI interpreter: Queuing the %s user function for asynchronous execution.\n" % uf)
201
202
203 fn = self._get_backend(uf)
204
205
206 self._interpreter_thread.queue(fn, *args, **kwds)
207
208
209
211 """The threaded interpreter."""
212
214 """Initialise the object."""
215
216
217 Thread.__init__(self)
218
219
220 self.daemon = True
221
222
223 self._queue = Queue()
224
225
226 self._uf_list = []
227
228
229 self._exit = False
230
231
233 """Is the queue empty?"""
234
235
236 if status.exec_lock.locked():
237 return False
238
239
240 elif len(self._uf_list):
241 return False
242
243
244 else:
245 return True
246
247
249 """Cause the thread to exit once all currently queued user functions are processed."""
250
251
252 self._exit = True
253
254
255 self._queue.put([None, None, None])
256
257
259 """Wrapper method for the Queue.join() method."""
260
261
262 self._queue.join()
263
264
265 - def queue(self, fn, *args, **kwds):
266 """Queue up a user function for asynchronous execution.
267
268 @param fn: The user function as a string.
269 @type fn: str
270 @param args: The user function arguments.
271 @type args: any arguments
272 @param kwds: The user function keyword arguments.
273 @type kwds: any keyword arguments
274 """
275
276
277 self._uf_list.append(repr(fn))
278
279
280 self._queue.put([fn, args, kwds])
281
282
284 """Execute the thread."""
285
286
287 while not self._exit:
288
289 fn, args, kwds = self._queue.get()
290
291
292 if fn == None:
293 continue
294
295
296 status.exec_lock.acquire('gui', mode='interpreter thread')
297
298
299 try:
300 apply(fn, args, kwds)
301
302
303 except AllRelaxErrors, instance:
304
305 wx.CallAfter(gui_raise, instance, raise_flag=False)
306
307
308 except:
309
310 print_exc()
311
312
313 finally:
314
315 self._queue.task_done()
316
317
318 status.exec_lock.release()
319
320
321 self._uf_list.pop(self._uf_list.index(repr(fn)))
322
323
324 status.observers.gui_uf.notify()
325