blob: 7aa6579efe4e2ce3246598192d96ea2de57e1695 [file] [log] [blame]
Guido van Rossumad50ca92002-12-30 22:30:22 +00001"""Drop-in replacement for the thread module.
2
3Meant to be used as a brain-dead substitute so that threaded code does
4not need to be rewritten for when the thread module is not present.
5
6Suggested usage is::
Tim Peters2c60f7a2003-01-29 03:49:43 +00007
Guido van Rossumad50ca92002-12-30 22:30:22 +00008 try:
Georg Brandl2067bfd2008-05-25 13:05:15 +00009 import _thread
Guido van Rossumad50ca92002-12-30 22:30:22 +000010 except ImportError:
Georg Brandl2067bfd2008-05-25 13:05:15 +000011 import _dummy_thread as _thread
Guido van Rossumad50ca92002-12-30 22:30:22 +000012
13"""
Thomas Wouters9fe394c2007-02-05 01:24:16 +000014# Exports only things specified by thread documentation;
15# skipping obsolete synonyms allocate(), start_new(), exit_thread().
Guido van Rossumad50ca92002-12-30 22:30:22 +000016__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock',
Brett Cannon4e64d782003-06-13 23:44:35 +000017 'interrupt_main', 'LockType']
Guido van Rossumad50ca92002-12-30 22:30:22 +000018
19import traceback as _traceback
20
21class error(Exception):
Georg Brandl2067bfd2008-05-25 13:05:15 +000022 """Dummy implementation of _thread.error."""
Guido van Rossumad50ca92002-12-30 22:30:22 +000023
24 def __init__(self, *args):
25 self.args = args
26
27def start_new_thread(function, args, kwargs={}):
Georg Brandl2067bfd2008-05-25 13:05:15 +000028 """Dummy implementation of _thread.start_new_thread().
Guido van Rossumad50ca92002-12-30 22:30:22 +000029
30 Compatibility is maintained by making sure that ``args`` is a
31 tuple and ``kwargs`` is a dictionary. If an exception is raised
Georg Brandl2067bfd2008-05-25 13:05:15 +000032 and it is SystemExit (which can be done by _thread.exit()) it is
Guido van Rossumad50ca92002-12-30 22:30:22 +000033 caught and nothing is done; all other exceptions are printed out
34 by using traceback.print_exc().
35
Brett Cannon4e64d782003-06-13 23:44:35 +000036 If the executed function calls interrupt_main the KeyboardInterrupt will be
37 raised when the function returns.
38
Guido van Rossumad50ca92002-12-30 22:30:22 +000039 """
40 if type(args) != type(tuple()):
41 raise TypeError("2nd arg must be a tuple")
42 if type(kwargs) != type(dict()):
43 raise TypeError("3rd arg must be a dict")
Brett Cannon91012fe2003-06-13 23:56:32 +000044 global _main
45 _main = False
Guido van Rossumad50ca92002-12-30 22:30:22 +000046 try:
47 function(*args, **kwargs)
48 except SystemExit:
49 pass
50 except:
51 _traceback.print_exc()
Brett Cannon91012fe2003-06-13 23:56:32 +000052 _main = True
53 global _interrupt
Brett Cannon4e64d782003-06-13 23:44:35 +000054 if _interrupt:
Brett Cannon4e64d782003-06-13 23:44:35 +000055 _interrupt = False
56 raise KeyboardInterrupt
Guido van Rossumad50ca92002-12-30 22:30:22 +000057
58def exit():
Georg Brandl2067bfd2008-05-25 13:05:15 +000059 """Dummy implementation of _thread.exit()."""
Guido van Rossumad50ca92002-12-30 22:30:22 +000060 raise SystemExit
61
62def get_ident():
Georg Brandl2067bfd2008-05-25 13:05:15 +000063 """Dummy implementation of _thread.get_ident().
Guido van Rossumad50ca92002-12-30 22:30:22 +000064
Georg Brandl2067bfd2008-05-25 13:05:15 +000065 Since this module should only be used when _threadmodule is not
Guido van Rossumad50ca92002-12-30 22:30:22 +000066 available, it is safe to assume that the current process is the
67 only thread. Thus a constant can be safely returned.
68 """
69 return -1
70
71def allocate_lock():
Georg Brandl2067bfd2008-05-25 13:05:15 +000072 """Dummy implementation of _thread.allocate_lock()."""
Guido van Rossumad50ca92002-12-30 22:30:22 +000073 return LockType()
74
Thomas Wouters0e3f5912006-08-11 14:57:12 +000075def stack_size(size=None):
Georg Brandl2067bfd2008-05-25 13:05:15 +000076 """Dummy implementation of _thread.stack_size()."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +000077 if size is not None:
78 raise error("setting thread stack size not supported")
79 return 0
80
Guido van Rossumad50ca92002-12-30 22:30:22 +000081class LockType(object):
Georg Brandl2067bfd2008-05-25 13:05:15 +000082 """Class implementing dummy implementation of _thread.LockType.
Tim Peters2c60f7a2003-01-29 03:49:43 +000083
Guido van Rossumad50ca92002-12-30 22:30:22 +000084 Compatibility is maintained by maintaining self.locked_status
85 which is a boolean that stores the state of the lock. Pickling of
Georg Brandl2067bfd2008-05-25 13:05:15 +000086 the lock, though, should not be done since if the _thread module is
Guido van Rossumad50ca92002-12-30 22:30:22 +000087 then used with an unpickled ``lock()`` from here problems could
88 occur from this class not having atomic methods.
89
90 """
91
92 def __init__(self):
93 self.locked_status = False
Tim Peters2c60f7a2003-01-29 03:49:43 +000094
Guido van Rossumad50ca92002-12-30 22:30:22 +000095 def acquire(self, waitflag=None):
96 """Dummy implementation of acquire().
97
98 For blocking calls, self.locked_status is automatically set to
99 True and returned appropriately based on value of
100 ``waitflag``. If it is non-blocking, then the value is
101 actually checked and not set if it is already acquired. This
102 is all done so that threading.Condition's assert statements
103 aren't triggered and throw a little fit.
104
105 """
Brett Cannon40c8f232008-07-13 01:19:15 +0000106 if waitflag is None or waitflag:
Guido van Rossumad50ca92002-12-30 22:30:22 +0000107 self.locked_status = True
Brett Cannon40c8f232008-07-13 01:19:15 +0000108 return True
109 else:
Guido van Rossumad50ca92002-12-30 22:30:22 +0000110 if not self.locked_status:
111 self.locked_status = True
112 return True
113 else:
114 return False
Guido van Rossumad50ca92002-12-30 22:30:22 +0000115
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000116 __enter__ = acquire
117
118 def __exit__(self, typ, val, tb):
119 self.release()
120
Guido van Rossumad50ca92002-12-30 22:30:22 +0000121 def release(self):
122 """Release the dummy lock."""
123 # XXX Perhaps shouldn't actually bother to test? Could lead
124 # to problems for complex, threaded code.
125 if not self.locked_status:
126 raise error
127 self.locked_status = False
128 return True
129
130 def locked(self):
131 return self.locked_status
Brett Cannon4e64d782003-06-13 23:44:35 +0000132
Brett Cannon91012fe2003-06-13 23:56:32 +0000133# Used to signal that interrupt_main was called in a "thread"
Brett Cannon4e64d782003-06-13 23:44:35 +0000134_interrupt = False
Brett Cannon91012fe2003-06-13 23:56:32 +0000135# True when not executing in a "thread"
136_main = True
Brett Cannon4e64d782003-06-13 23:44:35 +0000137
138def interrupt_main():
139 """Set _interrupt flag to True to have start_new_thread raise
140 KeyboardInterrupt upon exiting."""
Brett Cannon91012fe2003-06-13 23:56:32 +0000141 if _main:
142 raise KeyboardInterrupt
143 else:
144 global _interrupt
145 _interrupt = True