mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
target: Allow reuse of a connection once the owning thread is terminated
Once a thread exits, the connection instance it was using can be returned to the pool so it can be reused by another thread. Since there is no per-thread equivalent to atexit, this is achieved by returning the connection to the pool after every top-level method call that uses it directly, so the object the user can get by accessing Target.conn can change after each call to Target method.
This commit is contained in:
parent
1d6a007bad
commit
165b87f248
@ -103,7 +103,8 @@ def call_conn(f):
|
|||||||
|
|
||||||
@functools.wraps(f)
|
@functools.wraps(f)
|
||||||
def wrapper(self, *args, **kwargs):
|
def wrapper(self, *args, **kwargs):
|
||||||
reentered = self.conn.is_in_use
|
conn = self.conn
|
||||||
|
reentered = conn.is_in_use
|
||||||
disconnect = False
|
disconnect = False
|
||||||
try:
|
try:
|
||||||
# If the connection was already in use we need to use a different
|
# If the connection was already in use we need to use a different
|
||||||
@ -113,8 +114,9 @@ def call_conn(f):
|
|||||||
if reentered:
|
if reentered:
|
||||||
# Shallow copy so we can use another connection instance
|
# Shallow copy so we can use another connection instance
|
||||||
_self = copy.copy(self)
|
_self = copy.copy(self)
|
||||||
_self.conn = _self.get_connection()
|
new_conn = _self.get_connection()
|
||||||
assert self.conn is not _self.conn
|
assert conn is not new_conn
|
||||||
|
_self.conn = new_conn
|
||||||
disconnect = True
|
disconnect = True
|
||||||
else:
|
else:
|
||||||
_self = self
|
_self = self
|
||||||
@ -122,6 +124,13 @@ def call_conn(f):
|
|||||||
finally:
|
finally:
|
||||||
if disconnect:
|
if disconnect:
|
||||||
_self.disconnect()
|
_self.disconnect()
|
||||||
|
elif not reentered:
|
||||||
|
# Return the connection to the pool, so if we end up exiting
|
||||||
|
# the thread the connection can then be reused by another
|
||||||
|
# thread.
|
||||||
|
del self.conn
|
||||||
|
with self._lock:
|
||||||
|
self._unused_conns.add(conn)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
@ -284,7 +293,8 @@ class Target(object):
|
|||||||
@tls_property
|
@tls_property
|
||||||
def _conn(self):
|
def _conn(self):
|
||||||
try:
|
try:
|
||||||
return self._unused_conns.pop()
|
with self._lock:
|
||||||
|
return self._unused_conns.pop()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return self.get_connection()
|
return self.get_connection()
|
||||||
|
|
||||||
@ -311,6 +321,8 @@ class Target(object):
|
|||||||
is_container=False,
|
is_container=False,
|
||||||
max_async=50,
|
max_async=50,
|
||||||
):
|
):
|
||||||
|
|
||||||
|
self._lock = threading.RLock()
|
||||||
self._async_pool = None
|
self._async_pool = None
|
||||||
self._async_pool_size = None
|
self._async_pool_size = None
|
||||||
self._unused_conns = set()
|
self._unused_conns = set()
|
||||||
@ -435,6 +447,7 @@ class Target(object):
|
|||||||
ignored.update((
|
ignored.update((
|
||||||
'_async_pool',
|
'_async_pool',
|
||||||
'_unused_conns',
|
'_unused_conns',
|
||||||
|
'_lock',
|
||||||
))
|
))
|
||||||
return {
|
return {
|
||||||
k: v
|
k: v
|
||||||
@ -450,6 +463,7 @@ class Target(object):
|
|||||||
else:
|
else:
|
||||||
self._async_pool = ThreadPoolExecutor(pool_size)
|
self._async_pool = ThreadPoolExecutor(pool_size)
|
||||||
self._unused_conns = set()
|
self._unused_conns = set()
|
||||||
|
self._lock = threading.RLock()
|
||||||
|
|
||||||
# connection and initialization
|
# connection and initialization
|
||||||
|
|
||||||
@ -542,6 +556,13 @@ class Target(object):
|
|||||||
if pool is not None:
|
if pool is not None:
|
||||||
pool.__exit__(None, None, None)
|
pool.__exit__(None, None, None)
|
||||||
|
|
||||||
|
with self._lock:
|
||||||
|
connections = self._conn.get_all_values()
|
||||||
|
for conn in itertools.chain(connections, self._unused_conns):
|
||||||
|
conn.close()
|
||||||
|
if self._async_pool is not None:
|
||||||
|
self._async_pool.__exit__(None, None, None)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user