blob: 36e5f38ae0e8e276e4b3fb70305f6cb84e7cc0b9 [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
Brett Cannoncd171c82013-07-04 17:43:24 -040010 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
Antoine Pitrou7c3e5772010-04-14 15:44:10 +000019# A dummy value
20TIMEOUT_MAX = 2**31
Guido van Rossumad50ca92002-12-30 22:30:22 +000021
Antoine Pitroudb1bad22010-11-05 19:58:28 +000022# NOTE: this module can be imported early in the extension building process,
23# and so top level imports of other modules should be avoided. Instead, all
24# imports are done when needed on a function-by-function basis. Since threads
25# are disabled, the import lock should not be an issue anyway (??).
26
Antoine Pitrou819c40f2011-03-01 23:05:42 +000027error = RuntimeError
Guido van Rossumad50ca92002-12-30 22:30:22 +000028
29def start_new_thread(function, args, kwargs={}):
Georg Brandl2067bfd2008-05-25 13:05:15 +000030 """Dummy implementation of _thread.start_new_thread().
Guido van Rossumad50ca92002-12-30 22:30:22 +000031
32 Compatibility is maintained by making sure that ``args`` is a
33 tuple and ``kwargs`` is a dictionary. If an exception is raised
Georg Brandl2067bfd2008-05-25 13:05:15 +000034 and it is SystemExit (which can be done by _thread.exit()) it is
Guido van Rossumad50ca92002-12-30 22:30:22 +000035 caught and nothing is done; all other exceptions are printed out
36 by using traceback.print_exc().
37
Brett Cannon4e64d782003-06-13 23:44:35 +000038 If the executed function calls interrupt_main the KeyboardInterrupt will be
39 raised when the function returns.
40
Guido van Rossumad50ca92002-12-30 22:30:22 +000041 """
42 if type(args) != type(tuple()):
43 raise TypeError("2nd arg must be a tuple")
44 if type(kwargs) != type(dict()):
45 raise TypeError("3rd arg must be a dict")
Brett Cannon91012fe2003-06-13 23:56:32 +000046 global _main
47 _main = False
Guido van Rossumad50ca92002-12-30 22:30:22 +000048 try:
49 function(*args, **kwargs)
50 except SystemExit:
51 pass
52 except:
Antoine Pitroudb1bad22010-11-05 19:58:28 +000053 import traceback
54 traceback.print_exc()
Brett Cannon91012fe2003-06-13 23:56:32 +000055 _main = True
56 global _interrupt
Brett Cannon4e64d782003-06-13 23:44:35 +000057 if _interrupt:
Brett Cannon4e64d782003-06-13 23:44:35 +000058 _interrupt = False
59 raise KeyboardInterrupt
Guido van Rossumad50ca92002-12-30 22:30:22 +000060
61def exit():
Georg Brandl2067bfd2008-05-25 13:05:15 +000062 """Dummy implementation of _thread.exit()."""
Guido van Rossumad50ca92002-12-30 22:30:22 +000063 raise SystemExit
64
65def get_ident():
Georg Brandl2067bfd2008-05-25 13:05:15 +000066 """Dummy implementation of _thread.get_ident().
Guido van Rossumad50ca92002-12-30 22:30:22 +000067
Georg Brandl2067bfd2008-05-25 13:05:15 +000068 Since this module should only be used when _threadmodule is not
Guido van Rossumad50ca92002-12-30 22:30:22 +000069 available, it is safe to assume that the current process is the
70 only thread. Thus a constant can be safely returned.
71 """
72 return -1
73
74def allocate_lock():
Georg Brandl2067bfd2008-05-25 13:05:15 +000075 """Dummy implementation of _thread.allocate_lock()."""
Guido van Rossumad50ca92002-12-30 22:30:22 +000076 return LockType()
77
Thomas Wouters0e3f5912006-08-11 14:57:12 +000078def stack_size(size=None):
Georg Brandl2067bfd2008-05-25 13:05:15 +000079 """Dummy implementation of _thread.stack_size()."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +000080 if size is not None:
81 raise error("setting thread stack size not supported")
82 return 0
83
Antoine Pitrou7b476992013-09-07 23:38:37 +020084def _set_sentinel():
85 """Dummy implementation of _thread._set_sentinel()."""
86 return LockType()
87
Guido van Rossumad50ca92002-12-30 22:30:22 +000088class LockType(object):
Georg Brandl2067bfd2008-05-25 13:05:15 +000089 """Class implementing dummy implementation of _thread.LockType.
Tim Peters2c60f7a2003-01-29 03:49:43 +000090
Guido van Rossumad50ca92002-12-30 22:30:22 +000091 Compatibility is maintained by maintaining self.locked_status
92 which is a boolean that stores the state of the lock. Pickling of
Georg Brandl2067bfd2008-05-25 13:05:15 +000093 the lock, though, should not be done since if the _thread module is
Guido van Rossumad50ca92002-12-30 22:30:22 +000094 then used with an unpickled ``lock()`` from here problems could
95 occur from this class not having atomic methods.
96
97 """
98
99 def __init__(self):
100 self.locked_status = False
Tim Peters2c60f7a2003-01-29 03:49:43 +0000101
Antoine Pitrou7c3e5772010-04-14 15:44:10 +0000102 def acquire(self, waitflag=None, timeout=-1):
Guido van Rossumad50ca92002-12-30 22:30:22 +0000103 """Dummy implementation of acquire().
104
105 For blocking calls, self.locked_status is automatically set to
106 True and returned appropriately based on value of
107 ``waitflag``. If it is non-blocking, then the value is
108 actually checked and not set if it is already acquired. This
109 is all done so that threading.Condition's assert statements
110 aren't triggered and throw a little fit.
111
112 """
Brett Cannon40c8f232008-07-13 01:19:15 +0000113 if waitflag is None or waitflag:
Guido van Rossumad50ca92002-12-30 22:30:22 +0000114 self.locked_status = True
Brett Cannon40c8f232008-07-13 01:19:15 +0000115 return True
116 else:
Guido van Rossumad50ca92002-12-30 22:30:22 +0000117 if not self.locked_status:
118 self.locked_status = True
119 return True
120 else:
Antoine Pitrou7c3e5772010-04-14 15:44:10 +0000121 if timeout > 0:
Antoine Pitroudb1bad22010-11-05 19:58:28 +0000122 import time
Antoine Pitrou7c3e5772010-04-14 15:44:10 +0000123 time.sleep(timeout)
Guido van Rossumad50ca92002-12-30 22:30:22 +0000124 return False
Guido van Rossumad50ca92002-12-30 22:30:22 +0000125
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000126 __enter__ = acquire
127
128 def __exit__(self, typ, val, tb):
129 self.release()
130
Guido van Rossumad50ca92002-12-30 22:30:22 +0000131 def release(self):
132 """Release the dummy lock."""
133 # XXX Perhaps shouldn't actually bother to test? Could lead
134 # to problems for complex, threaded code.
135 if not self.locked_status:
136 raise error
137 self.locked_status = False
138 return True
139
140 def locked(self):
141 return self.locked_status
Brett Cannon4e64d782003-06-13 23:44:35 +0000142
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700143 def __repr__(self):
144 return "<%s %s.%s object at %s>" % (
145 "locked" if self.locked_status else "unlocked",
146 self.__class__.__module__,
147 self.__class__.__qualname__,
148 hex(id(self))
149 )
150
Brett Cannon91012fe2003-06-13 23:56:32 +0000151# Used to signal that interrupt_main was called in a "thread"
Brett Cannon4e64d782003-06-13 23:44:35 +0000152_interrupt = False
Brett Cannon91012fe2003-06-13 23:56:32 +0000153# True when not executing in a "thread"
154_main = True
Brett Cannon4e64d782003-06-13 23:44:35 +0000155
156def interrupt_main():
157 """Set _interrupt flag to True to have start_new_thread raise
158 KeyboardInterrupt upon exiting."""
Brett Cannon91012fe2003-06-13 23:56:32 +0000159 if _main:
160 raise KeyboardInterrupt
161 else:
162 global _interrupt
163 _interrupt = True