OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.python.threadable -*- | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 | |
6 """ | |
7 A module that will allow your program to be multi-threaded, | |
8 micro-threaded, and single-threaded. Currently microthreads are | |
9 unimplemented. The idea is to abstract away some commonly used | |
10 functionality so that I don't have to special-case it in all programs. | |
11 """ | |
12 | |
13 import warnings | |
14 | |
15 from twisted.python import hook | |
16 | |
17 class DummyLock(object): | |
18 """ | |
19 Hack to allow locks to be unpickled on an unthreaded system. | |
20 """ | |
21 | |
22 def __reduce__(self): | |
23 return (unpickle_lock, ()) | |
24 | |
25 def unpickle_lock(): | |
26 if threadingmodule is not None: | |
27 return XLock() | |
28 else: | |
29 return DummyLock() | |
30 unpickle_lock.__safe_for_unpickling__ = True | |
31 | |
32 def _synchPre(self, *a, **b): | |
33 if '_threadable_lock' not in self.__dict__: | |
34 _synchLockCreator.acquire() | |
35 if '_threadable_lock' not in self.__dict__: | |
36 self.__dict__['_threadable_lock'] = XLock() | |
37 _synchLockCreator.release() | |
38 self._threadable_lock.acquire() | |
39 | |
40 def _synchPost(self, *a, **b): | |
41 self._threadable_lock.release() | |
42 | |
43 def synchronize(*klasses): | |
44 """Make all methods listed in each class' synchronized attribute synchronize
d. | |
45 | |
46 The synchronized attribute should be a list of strings, consisting of the | |
47 names of methods that must be synchronized. If we are running in threaded | |
48 mode these methods will be wrapped with a lock. | |
49 """ | |
50 if threadmodule is not None: | |
51 for klass in klasses: | |
52 for methodName in klass.synchronized: | |
53 hook.addPre(klass, methodName, _synchPre) | |
54 hook.addPost(klass, methodName, _synchPost) | |
55 | |
56 def init(with_threads=1): | |
57 """Initialize threading. | |
58 | |
59 Don't bother calling this. If it needs to happen, it will happen. | |
60 """ | |
61 global threaded, _synchLockCreator, XLock | |
62 | |
63 if with_threads: | |
64 if not threaded: | |
65 if threadmodule is not None: | |
66 threaded = True | |
67 | |
68 class XLock(threadingmodule._RLock, object): | |
69 def __reduce__(self): | |
70 return (unpickle_lock, ()) | |
71 | |
72 _synchLockCreator = XLock() | |
73 else: | |
74 raise RuntimeError("Cannot initialize threading, platform lacks
thread support") | |
75 else: | |
76 if threaded: | |
77 raise RuntimeError("Cannot uninitialize threads") | |
78 else: | |
79 pass | |
80 | |
81 _dummyID = object() | |
82 def getThreadID(): | |
83 if threadmodule is None: | |
84 return _dummyID | |
85 return threadmodule.get_ident() | |
86 | |
87 | |
88 def isInIOThread(): | |
89 """Are we in the thread responsable for I/O requests (the event loop)? | |
90 """ | |
91 return ioThread == getThreadID() | |
92 | |
93 | |
94 def registerAsIOThread(): | |
95 """Mark the current thread as responsable for I/O requests. | |
96 """ | |
97 global ioThread | |
98 ioThread = getThreadID() | |
99 | |
100 | |
101 ioThread = None | |
102 threaded = False | |
103 | |
104 def whenThreaded(cb): | |
105 warnings.warn("threadable.whenThreaded is deprecated. " | |
106 "Use application-level logic instead.", | |
107 DeprecationWarning, stacklevel=2) | |
108 cb() | |
109 | |
110 try: | |
111 import thread as threadmodule | |
112 import threading as threadingmodule | |
113 except ImportError: | |
114 threadmodule = None | |
115 threadingmodule = None | |
116 else: | |
117 init(True) | |
118 | |
119 __all__ = ['isInIOThread', 'registerAsIOThread', 'getThreadID', 'XLock', | |
120 'whenThreaded'] | |
OLD | NEW |