annotate Lib/_threading_local.py @ 87690:66c1c9f32567 default tip

Add use_weakref option to functools.lru_cache The use_weakref option makes lru_cache create weak references to the function arguments when creating the cache key, which prevents them from staying in the memory forever even after all other references to them are gone. This is a proof of concept for http://bugs.python.org/issue19859
author Radomir Dopieralski <devel@sheep.art.pl>
date Tue, 03 Dec 2013 16:02:48 +0100
parents 3c9232a684ae
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
37879
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
1 """Thread-local objects.
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
2
37879
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
3 (Note that this module provides a Python version of the threading.local
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
4 class. Depending on the version of Python you're using, there may be a
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
5 faster one available. You should always import the `local` class from
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
6 `threading`.)
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
7
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
8 Thread-local objects support the management of thread-local data.
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
9 If you have data that you want to be local to a thread, simply create
32686
9a3b4219bcbe Typo fixes
Andrew M. Kuchling <amk@amk.ca>
parents: 32673
diff changeset
10 a thread-local object and use its attributes:
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
11
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
12 >>> mydata = local()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
13 >>> mydata.number = 42
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
14 >>> mydata.number
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
15 42
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
16
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
17 You can also access the local-object's dictionary:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
18
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
19 >>> mydata.__dict__
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
20 {'number': 42}
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
21 >>> mydata.__dict__.setdefault('widgets', [])
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
22 []
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
23 >>> mydata.widgets
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
24 []
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
25
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
26 What's important about thread-local objects is that their data are
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
27 local to a thread. If we access the data in a different thread:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
28
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
29 >>> log = []
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
30 >>> def f():
40809
f340cb045bf9 - PEP 3106: dict.iterkeys(), .iteritems(), .itervalues() are now gone;
Guido van Rossum <guido@python.org>
parents: 37879
diff changeset
31 ... items = sorted(mydata.__dict__.items())
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
32 ... log.append(items)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
33 ... mydata.number = 11
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
34 ... log.append(mydata.number)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
35
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
36 >>> import threading
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
37 >>> thread = threading.Thread(target=f)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
38 >>> thread.start()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
39 >>> thread.join()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
40 >>> log
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
41 [[], 11]
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
42
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
43 we get different data. Furthermore, changes made in the other thread
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
44 don't affect data seen in this thread:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
45
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
46 >>> mydata.number
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
47 42
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
48
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
49 Of course, values you get from a local object, including a __dict__
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
50 attribute, are for whatever thread was current at the time the
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
51 attribute was read. For that reason, you generally don't want to save
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
52 these values across threads, as they apply only to the thread they
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
53 came from.
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
54
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
55 You can create custom local objects by subclassing the local class:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
56
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
57 >>> class MyLocal(local):
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
58 ... number = 2
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
59 ... initialized = False
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
60 ... def __init__(self, **kw):
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
61 ... if self.initialized:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
62 ... raise SystemError('__init__ called too many times')
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
63 ... self.initialized = True
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
64 ... self.__dict__.update(kw)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
65 ... def squared(self):
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
66 ... return self.number ** 2
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
67
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
68 This can be useful to support default values, methods and
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
69 initialization. Note that if you define an __init__ method, it will be
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
70 called each time the local object is used in a separate thread. This
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
71 is necessary to initialize each thread's dictionary.
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
72
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
73 Now if we create a local object:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
74
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
75 >>> mydata = MyLocal(color='red')
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
76
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
77 Now we have a default number:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
78
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
79 >>> mydata.number
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
80 2
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
81
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
82 an initial color:
32736
c3a096bfbd6b Whitespace normalization, via reindent.py.
Tim Peters <tim.peters@gmail.com>
parents: 32686
diff changeset
83
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
84 >>> mydata.color
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
85 'red'
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
86 >>> del mydata.color
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
87
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
88 And a method that operates on the data:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
89
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
90 >>> mydata.squared()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
91 4
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
92
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
93 As before, we can access the data in a separate thread:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
94
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
95 >>> log = []
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
96 >>> thread = threading.Thread(target=f)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
97 >>> thread.start()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
98 >>> thread.join()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
99 >>> log
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
100 [[('color', 'red'), ('initialized', True)], 11]
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
101
32686
9a3b4219bcbe Typo fixes
Andrew M. Kuchling <amk@amk.ca>
parents: 32673
diff changeset
102 without affecting this thread's data:
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
103
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
104 >>> mydata.number
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
105 2
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
106 >>> mydata.color
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
107 Traceback (most recent call last):
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
108 ...
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
109 AttributeError: 'MyLocal' object has no attribute 'color'
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
110
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
111 Note that subclasses can define slots, but they are not thread
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
112 local. They are shared across threads:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
113
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
114 >>> class MyLocal(local):
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
115 ... __slots__ = 'number'
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
116
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
117 >>> mydata = MyLocal()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
118 >>> mydata.number = 42
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
119 >>> mydata.color = 'red'
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
120
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
121 So, the separate thread:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
122
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
123 >>> thread = threading.Thread(target=f)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
124 >>> thread.start()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
125 >>> thread.join()
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
126
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
127 affects what we see:
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
128
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
129 >>> mydata.number
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
130 11
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
131
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
132 >>> del mydata
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
133 """
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
134
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
135 from weakref import ref
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
136 from contextlib import contextmanager
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
137
37879
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
138 __all__ = ["local"]
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
139
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
140 # We need to use objects from the threading module, but the threading
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
141 # module may also want to use our `local` class, if support for locals
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
142 # isn't compiled in to the `thread` module. This creates potential problems
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
143 # with circular imports. For that reason, we don't import `threading`
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
144 # until the bottom of this file (a hack sufficient to worm around the
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
145 # potential problems). Note that all platforms on CPython do have support
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
146 # for locals in the `thread` module, and there is no circular import problem
37879
f731859e9b3b Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
Thomas Wouters <thomas@python.org>
parents: 35941
diff changeset
147 # then, so problems introduced by fiddling the order of imports here won't
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
148 # manifest.
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
149
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
150 class _localimpl:
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
151 """A class managing thread-local dicts"""
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
152 __slots__ = 'key', 'dicts', 'localargs', 'locallock', '__weakref__'
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
153
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
154 def __init__(self):
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
155 # The key used in the Thread objects' attribute dicts.
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
156 # We keep it a string for speed but make it unlikely to clash with
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
157 # a "real" attribute.
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
158 self.key = '_threading_local._localimpl.' + str(id(self))
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
159 # { id(Thread) -> (ref(Thread), thread-local dict) }
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
160 self.dicts = {}
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
161
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
162 def get_dict(self):
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
163 """Return the dict for the current thread. Raises KeyError if none
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
164 defined."""
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
165 thread = current_thread()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
166 return self.dicts[id(thread)][1]
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
167
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
168 def create_dict(self):
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
169 """Create a new dict for the current thread, and return it."""
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
170 localdict = {}
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
171 key = self.key
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
172 thread = current_thread()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
173 idt = id(thread)
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
174 def local_deleted(_, key=key):
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
175 # When the localimpl is deleted, remove the thread attribute.
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
176 thread = wrthread()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
177 if thread is not None:
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
178 del thread.__dict__[key]
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
179 def thread_deleted(_, idt=idt):
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
180 # When the thread is deleted, remove the local dict.
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
181 # Note that this is suboptimal if the thread object gets
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
182 # caught in a reference loop. We would like to be called
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
183 # as soon as the OS-level thread ends instead.
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
184 local = wrlocal()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
185 if local is not None:
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
186 dct = local.dicts.pop(idt)
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
187 wrlocal = ref(self, local_deleted)
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
188 wrthread = ref(thread, thread_deleted)
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
189 thread.__dict__[key] = wrlocal
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
190 self.dicts[idt] = wrthread, localdict
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
191 return localdict
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
192
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
193
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
194 @contextmanager
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
195 def _patch(self):
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
196 impl = object.__getattribute__(self, '_local__impl')
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
197 try:
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
198 dct = impl.get_dict()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
199 except KeyError:
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
200 dct = impl.create_dict()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
201 args, kw = impl.localargs
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
202 self.__init__(*args, **kw)
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
203 with impl.locallock:
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
204 object.__setattr__(self, '__dict__', dct)
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
205 yield
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
206
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
207
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
208 class local:
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
209 __slots__ = '_local__impl', '__dict__'
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
210
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
211 def __new__(cls, *args, **kw):
59031
ef732c3db63d fixes issue #1522237, bad init check in _threading_local
Jack Diederich <jackdied@gmail.com>
parents: 57121
diff changeset
212 if (args or kw) and (cls.__init__ is object.__init__):
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
213 raise TypeError("Initialization arguments are not supported")
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
214 self = object.__new__(cls)
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
215 impl = _localimpl()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
216 impl.localargs = (args, kw)
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
217 impl.locallock = RLock()
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
218 object.__setattr__(self, '_local__impl', impl)
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
219 # We need to create the thread dict in anticipation of
35941
033bb4db5ae8 Fix some comment typos
Neal Norwitz <nnorwitz@gmail.com>
parents: 32736
diff changeset
220 # __init__ being called, to make sure we don't call it
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
221 # again ourselves.
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
222 impl.create_dict()
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
223 return self
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
224
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
225 def __getattribute__(self, name):
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
226 with _patch(self):
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
227 return object.__getattribute__(self, name)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
228
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
229 def __setattr__(self, name, value):
64299
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
230 if name == '__dict__':
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
231 raise AttributeError(
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
232 "%r object attribute '__dict__' is read-only"
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
233 % self.__class__.__name__)
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
234 with _patch(self):
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
235 return object.__setattr__(self, name, value)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
236
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
237 def __delattr__(self, name):
64299
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
238 if name == '__dict__':
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
239 raise AttributeError(
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
240 "%r object attribute '__dict__' is read-only"
4c978cd3640f Merged revisions 84344 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 57121
diff changeset
241 % self.__class__.__name__)
64543
c2d6f0cf926a Issue #9707: Rewritten reference implementation of threading.local which
Antoine Pitrou <solipsis@pitrou.net>
parents: 64298
diff changeset
242 with _patch(self):
32673
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
243 return object.__delattr__(self, name)
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
244
97768d87394a Implemented thread-local data as proposed on python-dev:
Jim Fulton <jim@zope.com>
parents:
diff changeset
245
47615
045f83a1b864 Merged revisions 64125 via svnmerge from
Benjamin Peterson <benjamin@python.org>
parents: 40809
diff changeset
246 from threading import current_thread, RLock