diff --git a/CHANGES b/CHANGES index 2b0afb3ce1e1c7e8455fecc408d0a98f75b973a8..865cf83d68e41c4623e6f02faa641b71cb8b3404 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 2d4992ebecc206a810b3e975d74f6124b3f9f5b9..40f4dcf7f178a8993fed60f1c6a0b50641c9344f 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 ); } }