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