1 #!/usr/bin/env python2.5
3 # Copyright (c) 2011 Neal H. Walfield <neal@walfield.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 _run_in_main_thread = None
24 def init(run_in_main_thread=None):
26 run_in_main_thread is a function that takes a single argument, a
27 callable and returns False. run_in_main_thread should run the
28 function in the main thread.
30 If you are using glib, gobject.idle_add (the default) is
31 sufficient. (gobject.idle_add is thread-safe.)
33 if run_in_main_thread is None:
35 run_in_main_thread = gobject.idle_add
37 global _run_in_main_thread
38 assert _run_in_main_thread is None
39 _run_in_main_thread = run_in_main_thread
42 _main_thread = threading.currentThread ()
44 def execute(func, *args, **kwargs):
46 Execute FUNC in the main thread.
48 If kwargs['async'] exists and is True, the function is executed
49 asynchronously (i.e., the thread does not wait for the function to
50 return in which case the function's return value is discarded).
51 Otherwise, this function waits until the function is executed and
52 returns its return value.
56 async = kwargs['async']
61 if threading.currentThread() == _main_thread:
64 func (*args, **kwargs)
66 print ("mainthread.execute: Executing %s: %s"
67 % (func, traceback.format_exc ()))
70 return func (*args, **kwargs)
72 assert _run_in_main_thread is not None, \
73 "You can't call this function from a non-main thread until you've called init()"
76 cond = threading.Condition()
79 result['done'] = False
83 # Execute the function.
84 assert threading.currentThread() == _main_thread
87 result['result'] = func (*args, **kwargs)
89 print ("mainthread.execute: Executing %s: %s"
90 % (func, traceback.format_exc ()))
104 _run_in_main_thread (doit())
107 # Don't wait for the method to complete execution.
110 # Wait for the result to become available.
111 while not result['done']:
114 return result.get ('result', None)
116 if __name__ == "__main__":
122 def in_main_thread(test_num):
123 assert threading.currentThread() == _main_thread, \
124 "Test %d failed" % (test_num,)
127 mainloop = gobject.MainLoop()
128 gobject.threads_init()
130 assert execute (in_main_thread, 1) == 1
131 assert (execute (in_main_thread, 2, async=False) == 2)
132 execute (in_main_thread, 3, async=True)
134 class T(threading.Thread):
136 threading.Thread.__init__(self)
139 assert threading.currentThread() != _main_thread
141 assert execute (in_main_thread, 4) == 4
142 assert (execute (in_main_thread, 5, async=False) == 5)
143 execute (in_main_thread, 6, async=True)
144 execute (mainloop.quit, async=False)
151 gobject.idle_add (start_thread)
155 def wrapper(*args, **kwargs):
156 return execute (f, *args, **kwargs)