blob: e4bf05a2cac4262cf6e82a2aa3b0dce62fca796d [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:
9 import thread
10 except ImportError:
11 import dummy_thread as thread
12
13"""
14__author__ = "Brett Cannon"
15__email__ = "brett@python.org"
16
17# Exports only things specified by thread documentation
18# (skipping obsolete synonyms allocate(), start_new(), exit_thread())
19__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock',
20 'LockType']
21
22import traceback as _traceback
23
24class error(Exception):
25 """Dummy implementation of thread.error."""
26
27 def __init__(self, *args):
28 self.args = args
29
30def start_new_thread(function, args, kwargs={}):
31 """Dummy implementation of thread.start_new_thread().
32
33 Compatibility is maintained by making sure that ``args`` is a
34 tuple and ``kwargs`` is a dictionary. If an exception is raised
35 and it is SystemExit (which can be done by thread.exit()) it is
36 caught and nothing is done; all other exceptions are printed out
37 by using traceback.print_exc().
38
39 """
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")
44 try:
45 function(*args, **kwargs)
46 except SystemExit:
47 pass
48 except:
49 _traceback.print_exc()
50
51def exit():
52 """Dummy implementation of thread.exit()."""
53 raise SystemExit
54
55def get_ident():
56 """Dummy implementation of thread.get_ident().
57
58 Since this module should only be used when threadmodule is not
59 available, it is safe to assume that the current process is the
60 only thread. Thus a constant can be safely returned.
61 """
62 return -1
63
64def allocate_lock():
65 """Dummy implementation of thread.allocate_lock()."""
66 return LockType()
67
68class LockType(object):
69 """Class implementing dummy implementation of thread.LockType.
Tim Peters2c60f7a2003-01-29 03:49:43 +000070
Guido van Rossumad50ca92002-12-30 22:30:22 +000071 Compatibility is maintained by maintaining self.locked_status
72 which is a boolean that stores the state of the lock. Pickling of
73 the lock, though, should not be done since if the thread module is
74 then used with an unpickled ``lock()`` from here problems could
75 occur from this class not having atomic methods.
76
77 """
78
79 def __init__(self):
80 self.locked_status = False
Tim Peters2c60f7a2003-01-29 03:49:43 +000081
Guido van Rossumad50ca92002-12-30 22:30:22 +000082 def acquire(self, waitflag=None):
83 """Dummy implementation of acquire().
84
85 For blocking calls, self.locked_status is automatically set to
86 True and returned appropriately based on value of
87 ``waitflag``. If it is non-blocking, then the value is
88 actually checked and not set if it is already acquired. This
89 is all done so that threading.Condition's assert statements
90 aren't triggered and throw a little fit.
91
92 """
93 if waitflag is None:
94 self.locked_status = True
Tim Peters2c60f7a2003-01-29 03:49:43 +000095 return None
Guido van Rossumad50ca92002-12-30 22:30:22 +000096 elif not waitflag:
97 if not self.locked_status:
98 self.locked_status = True
99 return True
100 else:
101 return False
102 else:
103 self.locked_status = True
Tim Peters2c60f7a2003-01-29 03:49:43 +0000104 return True
Guido van Rossumad50ca92002-12-30 22:30:22 +0000105
106 def release(self):
107 """Release the dummy lock."""
108 # XXX Perhaps shouldn't actually bother to test? Could lead
109 # to problems for complex, threaded code.
110 if not self.locked_status:
111 raise error
112 self.locked_status = False
113 return True
114
115 def locked(self):
116 return self.locked_status