From 6efd35e0a248257817cd1b838560a94d25cbcae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Walld=C3=A9n?= <jonasw@roxen.com> Date: Wed, 4 Apr 2018 14:37:07 +0200 Subject: [PATCH] Added Thread.Farm()->set_thread_name_cb() to help applications that monitor thread creation and termination for the purpose of tracking thread names. --- CHANGES | 7 ++++-- lib/modules/Thread.pmod | 49 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 2b0afb3ce1..865cf83d68 100644 --- a/CHANGES +++ b/CHANGES @@ -758,8 +758,11 @@ New features o Thread - _sprintf() improvements: Thread.Mutex now prints the ID of the thread - holding the lock, and thread IDs are shown as hexadecimal numbers. + - _sprintf() improvements: Thread.Mutex now prints the ID of the thread + holding the lock, and thread IDs are shown as hexadecimal numbers. + + - Thread.Farm now supports a callback for thread creation and termination + for the purpose of tracking thread names. Bug fixes --------- diff --git a/lib/modules/Thread.pmod b/lib/modules/Thread.pmod index 2d4992ebec..40f4dcf7f1 100644 --- a/lib/modules/Thread.pmod +++ b/lib/modules/Thread.pmod @@ -406,6 +406,9 @@ optional class Farm protected Mutex mutex = Mutex(); protected Condition ft_cond = Condition(); protected Queue job_queue = Queue(); + protected object dispatcher_thread; + protected function(object, string:void) thread_name_cb; + protected string thread_name_prefix; //! An asynchronous result. class Result @@ -514,6 +517,16 @@ optional class Farm protected int ready; + void update_thread_name(int is_exiting) + { + if (thread_name_cb) { + string th_name = + !is_exiting && + sprintf("%s Handler 0x%x", thread_name_prefix, thread->id_number()); + thread_name_cb(thread, th_name); + } + } + void handler() { array(object|array(function|array)) q; @@ -540,11 +553,12 @@ optional class Farm if( st > max_time ) max_time = st; ft_cond->broadcast(); - } else { + } else { object lock = mutex->lock(); threads -= ({ this }); free_threads -= ({ this }); lock = 0; + update_thread_name(1); destruct(); return; } @@ -580,6 +594,7 @@ optional class Farm protected void create() { thread = thread_create( handler ); + update_thread_name(0); } @@ -623,6 +638,8 @@ optional class Farm { while( array q = [array]job_queue->read() ) aquire_thread()->run( q[1], q[0] ); + if (thread_name_cb) + thread_name_cb(this_thread(), 0); } protected class ValueAdjuster( object r, object r2, int i, mapping v ) @@ -776,6 +793,34 @@ optional class Farm return omnt; } + //! Provide a callback function to track names of threads created by the + //! farm. + //! + //! @param cb + //! The callback function. This will get invoked with the thread as the + //! first parameter and the name as the second whenever a thread is + //! created. When the same thread terminates the callback is invoked + //! again with @[0] as the second parameter. Set @[cb] to @[0] to stop + //! any previously registered callbacks from being called. + //! + //! @param prefix + //! An optional name prefix to distinguish different farms. If not given + //! a prefix will be generated automatically. + void set_thread_name_cb(function(object, string:void) cb, void|string prefix) + { + thread_name_cb = cb; + thread_name_prefix = + cb && + (prefix || sprintf("Thread.Farm 0x%x", dispatcher_thread->id_number())); + + // Give a name to all existing threads + if (thread_name_cb) { + thread_name_cb(dispatcher_thread, thread_name_prefix + " Dispatcher"); + foreach (threads, Handler t) + t->update_thread_name(0); + } + } + //! Get some statistics for the thread farm. string debug_status() { @@ -800,7 +845,7 @@ optional class Farm protected void create() { - thread_create( dispatcher ); + dispatcher_thread = thread_create( dispatcher ); } } -- GitLab