Updated script that can be controled by Nodejs web app
This commit is contained in:
176
lib/python3.13/site-packages/eventlet/green/thread.py
Normal file
176
lib/python3.13/site-packages/eventlet/green/thread.py
Normal file
@@ -0,0 +1,176 @@
|
||||
"""Implements the standard thread module, using greenthreads."""
|
||||
import _thread as __thread
|
||||
from eventlet.support import greenlets as greenlet
|
||||
from eventlet import greenthread
|
||||
from eventlet.timeout import with_timeout
|
||||
from eventlet.lock import Lock
|
||||
import sys
|
||||
|
||||
|
||||
__patched__ = ['Lock', 'LockType', '_ThreadHandle', '_count',
|
||||
'_get_main_thread_ident', '_local', '_make_thread_handle',
|
||||
'allocate', 'allocate_lock', 'exit', 'get_ident',
|
||||
'interrupt_main', 'stack_size', 'start_joinable_thread',
|
||||
'start_new', 'start_new_thread']
|
||||
|
||||
error = __thread.error
|
||||
LockType = Lock
|
||||
__threadcount = 0
|
||||
|
||||
if hasattr(__thread, "_is_main_interpreter"):
|
||||
_is_main_interpreter = __thread._is_main_interpreter
|
||||
|
||||
|
||||
def _set_sentinel():
|
||||
# TODO this is a dummy code, reimplementing this may be needed:
|
||||
# https://hg.python.org/cpython/file/b5e9bc4352e1/Modules/_threadmodule.c#l1203
|
||||
return allocate_lock()
|
||||
|
||||
|
||||
TIMEOUT_MAX = __thread.TIMEOUT_MAX
|
||||
|
||||
|
||||
def _count():
|
||||
return __threadcount
|
||||
|
||||
|
||||
def get_ident(gr=None):
|
||||
if gr is None:
|
||||
return id(greenlet.getcurrent())
|
||||
else:
|
||||
return id(gr)
|
||||
|
||||
|
||||
def __thread_body(func, args, kwargs):
|
||||
global __threadcount
|
||||
__threadcount += 1
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
finally:
|
||||
__threadcount -= 1
|
||||
|
||||
|
||||
class _ThreadHandle:
|
||||
def __init__(self, greenthread=None):
|
||||
self._greenthread = greenthread
|
||||
self._done = False
|
||||
|
||||
def _set_done(self):
|
||||
self._done = True
|
||||
|
||||
def is_done(self):
|
||||
return self._done
|
||||
|
||||
@property
|
||||
def ident(self):
|
||||
return get_ident(self._greenthread)
|
||||
|
||||
def join(self, timeout=None):
|
||||
if not hasattr(self._greenthread, "wait"):
|
||||
return
|
||||
if timeout is not None:
|
||||
return with_timeout(timeout, self._greenthread.wait)
|
||||
return self._greenthread.wait()
|
||||
|
||||
|
||||
def _make_thread_handle(ident):
|
||||
greenthread = greenlet.getcurrent()
|
||||
assert ident == get_ident(greenthread)
|
||||
return _ThreadHandle(greenthread=greenthread)
|
||||
|
||||
|
||||
def __spawn_green(function, args=(), kwargs=None, joinable=False):
|
||||
if ((3, 4) <= sys.version_info < (3, 13)
|
||||
and getattr(function, '__module__', '') == 'threading'
|
||||
and hasattr(function, '__self__')):
|
||||
# In Python 3.4-3.12, threading.Thread uses an internal lock
|
||||
# automatically released when the python thread state is deleted.
|
||||
# With monkey patching, eventlet uses green threads without python
|
||||
# thread state, so the lock is not automatically released.
|
||||
#
|
||||
# Wrap _bootstrap_inner() to release explicitly the thread state lock
|
||||
# when the thread completes.
|
||||
thread = function.__self__
|
||||
bootstrap_inner = thread._bootstrap_inner
|
||||
|
||||
def wrap_bootstrap_inner():
|
||||
try:
|
||||
bootstrap_inner()
|
||||
finally:
|
||||
# The lock can be cleared (ex: by a fork())
|
||||
if getattr(thread, "_tstate_lock", None) is not None:
|
||||
thread._tstate_lock.release()
|
||||
|
||||
thread._bootstrap_inner = wrap_bootstrap_inner
|
||||
|
||||
kwargs = kwargs or {}
|
||||
spawn_func = greenthread.spawn if joinable else greenthread.spawn_n
|
||||
return spawn_func(__thread_body, function, args, kwargs)
|
||||
|
||||
|
||||
def start_joinable_thread(function, handle=None, daemon=True):
|
||||
g = __spawn_green(function, joinable=True)
|
||||
if handle is None:
|
||||
handle = _ThreadHandle(greenthread=g)
|
||||
else:
|
||||
handle._greenthread = g
|
||||
return handle
|
||||
|
||||
|
||||
def start_new_thread(function, args=(), kwargs=None):
|
||||
g = __spawn_green(function, args=args, kwargs=kwargs)
|
||||
return get_ident(g)
|
||||
|
||||
|
||||
start_new = start_new_thread
|
||||
|
||||
|
||||
def _get_main_thread_ident():
|
||||
greenthread = greenlet.getcurrent()
|
||||
while greenthread.parent is not None:
|
||||
greenthread = greenthread.parent
|
||||
return get_ident(greenthread)
|
||||
|
||||
|
||||
def allocate_lock(*a):
|
||||
return LockType(1)
|
||||
|
||||
|
||||
allocate = allocate_lock
|
||||
|
||||
|
||||
def exit():
|
||||
raise greenlet.GreenletExit
|
||||
|
||||
|
||||
exit_thread = __thread.exit_thread
|
||||
|
||||
|
||||
def interrupt_main():
|
||||
curr = greenlet.getcurrent()
|
||||
if curr.parent and not curr.parent.dead:
|
||||
curr.parent.throw(KeyboardInterrupt())
|
||||
else:
|
||||
raise KeyboardInterrupt()
|
||||
|
||||
|
||||
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
|
||||
|
||||
from eventlet.corolocal import local as _local
|
||||
|
||||
if hasattr(__thread, 'daemon_threads_allowed'):
|
||||
daemon_threads_allowed = __thread.daemon_threads_allowed
|
||||
|
||||
if hasattr(__thread, '_shutdown'):
|
||||
_shutdown = __thread._shutdown
|
||||
Reference in New Issue
Block a user