# HG changeset patch # User Joshua Harlow # Date 1441135537 25200 # Tue Sep 01 12:25:37 2015 -0700 # Node ID 21c7f1439ee3cb4bab5af0bdcc8f1e35af3031f2 # Parent 0073f17ed1f8aa28aa98682c878e2d66af8719fd Add a 'on_new_thread' callback to concurrent thread executor This addition allows for users to provide a callback that will be called once per spawned thread. It can be used to setup thread local state (for example). diff -r 0073f17ed1f8 -r 21c7f1439ee3 Lib/concurrent/futures/thread.py --- a/Lib/concurrent/futures/thread.py Tue Sep 01 02:33:20 2015 -0700 +++ b/Lib/concurrent/futures/thread.py Tue Sep 01 12:25:37 2015 -0700 @@ -58,8 +58,13 @@ else: self.future.set_result(result) -def _worker(executor_reference, work_queue): +def _worker(executor_reference, work_queue, on_new_thread): try: + if on_new_thread is not None: + try: + on_new_thread() + finally: + del on_new_thread while True: work_item = work_queue.get(block=True) if work_item is not None: @@ -81,12 +86,15 @@ _base.LOGGER.critical('Exception in worker', exc_info=True) class ThreadPoolExecutor(_base.Executor): - def __init__(self, max_workers=None): + def __init__(self, max_workers=None, on_new_thread=None): """Initializes a new ThreadPoolExecutor instance. Args: max_workers: The maximum number of threads that can be used to execute the given calls. + on_new_thread: Callback that will be called by each newly spawned + thread; typically useful for setting up any thread local + state (or other thread-specific data). """ if max_workers is None: # Use this number because ThreadPoolExecutor is often @@ -95,6 +103,7 @@ if max_workers <= 0: raise ValueError("max_workers must be greater than 0") + self._on_new_thread = on_new_thread self._max_workers = max_workers self._work_queue = queue.Queue() self._threads = set() @@ -124,7 +133,8 @@ if len(self._threads) < self._max_workers: t = threading.Thread(target=_worker, args=(weakref.ref(self, weakref_cb), - self._work_queue)) + self._work_queue, + self._on_new_thread)) t.daemon = True t.start() self._threads.add(t)