Adjust the package revision; no actual code changes
[packages/trusty/python-eventlet.git] / eventlet / eventlet / green / threading.py
1 """Implements the standard threading module, using greenthreads."""
2 from eventlet import patcher
3 from eventlet.green import thread
4 from eventlet.green import time
5 from eventlet.support import greenlets as greenlet
6
7 __patched__ = ['_start_new_thread', '_allocate_lock', '_get_ident', '_sleep',
8                'local', 'stack_size', 'Lock', 'currentThread',
9                'current_thread', '_after_fork', '_shutdown']
10
11 __orig_threading = patcher.original('threading')
12 __threadlocal = __orig_threading.local()
13
14
15 patcher.inject(
16     'threading',
17     globals(),
18     ('thread', thread),
19     ('time', time))
20
21 del patcher
22
23
24 _count = 1
25
26
27 class _GreenThread(object):
28     """Wrapper for GreenThread objects to provide Thread-like attributes
29     and methods"""
30
31     def __init__(self, g):
32         global _count
33         self._g = g
34         self._name = 'GreenThread-%d' % _count
35         _count += 1
36
37     def __repr__(self):
38         return '<_GreenThread(%s, %r)>' % (self._name, self._g)
39
40     def join(self, timeout=None):
41         return self._g.wait()
42
43     def getName(self):
44         return self._name
45     get_name = getName
46
47     def setName(self, name):
48         self._name = str(name)
49     set_name = setName
50
51     name = property(getName, setName)
52
53     ident = property(lambda self: id(self._g))
54
55     def isAlive(self):
56         return True
57     is_alive = isAlive
58
59     daemon = property(lambda self: True)
60
61     def isDaemon(self):
62         return self.daemon
63     is_daemon = isDaemon
64
65
66 __threading = None
67
68
69 def _fixup_thread(t):
70     # Some third-party packages (lockfile) will try to patch the
71     # threading.Thread class with a get_name attribute if it doesn't
72     # exist. Since we might return Thread objects from the original
73     # threading package that won't get patched, let's make sure each
74     # individual object gets patched too our patched threading.Thread
75     # class has been patched. This is why monkey patching can be bad...
76     global __threading
77     if not __threading:
78         __threading = __import__('threading')
79
80     if (hasattr(__threading.Thread, 'get_name') and
81             not hasattr(t, 'get_name')):
82         t.get_name = t.getName
83     return t
84
85
86 def current_thread():
87     g = greenlet.getcurrent()
88     if not g:
89         # Not currently in a greenthread, fall back to standard function
90         return _fixup_thread(__orig_threading.current_thread())
91
92     try:
93         active = __threadlocal.active
94     except AttributeError:
95         active = __threadlocal.active = {}
96
97     try:
98         t = active[id(g)]
99     except KeyError:
100         # Add green thread to active if we can clean it up on exit
101         def cleanup(g):
102             del active[id(g)]
103         try:
104             g.link(cleanup)
105         except AttributeError:
106             # Not a GreenThread type, so there's no way to hook into
107             # the green thread exiting. Fall back to the standard
108             # function then.
109             t = _fixup_thread(__orig_threading.currentThread())
110         else:
111             t = active[id(g)] = _GreenThread(g)
112
113     return t
114
115 currentThread = current_thread