aboutsummaryrefslogtreecommitdiffstats
path: root/python/gevent/thread.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/gevent/thread.py')
-rw-r--r--python/gevent/thread.py115
1 files changed, 115 insertions, 0 deletions
diff --git a/python/gevent/thread.py b/python/gevent/thread.py
new file mode 100644
index 0000000..0a1af38
--- /dev/null
+++ b/python/gevent/thread.py
@@ -0,0 +1,115 @@
+"""
+Implementation of the standard :mod:`thread` module that spawns greenlets.
+
+.. note::
+
+ This module is a helper for :mod:`gevent.monkey` and is not
+ intended to be used directly. For spawning greenlets in your
+ applications, prefer higher level constructs like
+ :class:`gevent.Greenlet` class or :func:`gevent.spawn`.
+"""
+from __future__ import absolute_import
+import sys
+
+__implements__ = ['allocate_lock',
+ 'get_ident',
+ 'exit',
+ 'LockType',
+ 'stack_size',
+ 'start_new_thread',
+ '_local']
+
+__imports__ = ['error']
+if sys.version_info[0] <= 2:
+ import thread as __thread__ # pylint:disable=import-error
+else:
+ import _thread as __thread__ # pylint:disable=import-error
+ __target__ = '_thread'
+ __imports__ += ['RLock',
+ 'TIMEOUT_MAX',
+ 'allocate',
+ 'exit_thread',
+ 'interrupt_main',
+ 'start_new']
+error = __thread__.error
+from gevent._compat import PY3
+from gevent._compat import PYPY
+from gevent._util import copy_globals
+from gevent.hub import getcurrent, GreenletExit
+from gevent.greenlet import Greenlet
+from gevent.lock import BoundedSemaphore
+from gevent.local import local as _local
+
+
+def get_ident(gr=None):
+ if gr is None:
+ gr = getcurrent()
+ return id(gr)
+
+
+def start_new_thread(function, args=(), kwargs=None):
+ if kwargs is not None:
+ greenlet = Greenlet.spawn(function, *args, **kwargs)
+ else:
+ greenlet = Greenlet.spawn(function, *args)
+ return get_ident(greenlet)
+
+
+class LockType(BoundedSemaphore):
+ # Change the ValueError into the appropriate thread error
+ # and any other API changes we need to make to match behaviour
+ _OVER_RELEASE_ERROR = __thread__.error
+
+ if PYPY and PY3:
+ _OVER_RELEASE_ERROR = RuntimeError
+
+ if PY3:
+ _TIMEOUT_MAX = __thread__.TIMEOUT_MAX # python 2: pylint:disable=no-member
+
+ def acquire(self, blocking=True, timeout=-1):
+ # Transform the default -1 argument into the None that our
+ # semaphore implementation expects, and raise the same error
+ # the stdlib implementation does.
+ if timeout == -1:
+ timeout = None
+ if not blocking and timeout is not None:
+ raise ValueError("can't specify a timeout for a non-blocking call")
+ if timeout is not None:
+ if timeout < 0:
+ # in C: if(timeout < 0 && timeout != -1)
+ raise ValueError("timeout value must be strictly positive")
+ if timeout > self._TIMEOUT_MAX:
+ raise OverflowError('timeout value is too large')
+
+ return BoundedSemaphore.acquire(self, blocking, timeout)
+
+allocate_lock = LockType
+
+
+def exit():
+ raise GreenletExit
+
+
+if hasattr(__thread__, 'stack_size'):
+ _original_stack_size = __thread__.stack_size
+
+ def stack_size(size=None):
+ if size is None:
+ return _original_stack_size()
+ if size > _original_stack_size():
+ return _original_stack_size(size)
+ else:
+ pass
+ # not going to decrease stack_size, because otherwise other greenlets in this thread will suffer
+else:
+ __implements__.remove('stack_size')
+
+__imports__ = copy_globals(__thread__, globals(),
+ only_names=__imports__,
+ ignore_missing_names=True)
+
+__all__ = __implements__ + __imports__
+__all__.remove('_local')
+
+# XXX interrupt_main
+# XXX _count()