Mercurial > cpython-lru_cache-weakref
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 |
| 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 | 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 | 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 | 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 |
