mod to omnithread for NT.

Tristan Richardson tjr@orl.co.uk
Wed, 09 Jul 1997 11:49:48 +0100


>>>>>> "Matthew Newhook" <matthew_newhook@stratos.ca> writes:
>
> Hi,
>   What follows is a change to the omnithread library to allow an arbitrary
>   thread-wrapper function to be setup.  The function of this is to
>   allow some per-thread stuff to be setup for each thread that is
>   created.  We use this to create objectstore thread handles under NT.
> 
>   This implementation is ONLY for NT also.  If you use
>   omni_thread::set_thread_wrapper under something other that NT you
>   will get undefined symbols.
> 
>   Here is a sample that uses this new API:
> 
> ...
> 
> static void*
> thr_ret(void *arg)
> {
>     struct thread_arg* thr_arg = (struct thread_arg*)arg;
>     void* (*fn)(void*) = thr_arg->fn;
>     void* the_arg = thr_arg->arg;
>     delete thr_arg;
> 
>     void* rc;
>     OS_ESTABLISH_FAULT_HANDLER
>     rc = (*fn)(the_arg);
>     OS_END_FAULT_HANDLER
>     return rc;
> }
> 
> /*static*/ void
> c_ostore_handler::ostore_init()
> {
> 	omni_thread::set_thread_wrapper(thr_ret);
> }
> 

This is unnecessary.  The "wrapper" function is totally internal to the
omnithread implementation.  Matthew's example could be implemented more easily
without his set_thread_wrapper stuff, e.g.

    void // or void* for undetached
    my_thread_fn(void* arg)
    {
        OS_ESTABLISH_FAULT_HANDLER

        ... do whatever ...

        OS_END_FAULT_HANDLER
    }

where you create the thread with omni_thread::create(my_thread_fn,...).


There is one problem with this approach (which may be why Matthew _thought_
he needed to change the "wrapper" function).  If the thread calls
omni_thread::exit(), rather than just getting to the end of my_thread_fn()
then the "OS_END_FAULT_HANDLER" bit won't be invoked.  This is true also of
your set_thread_wrapper stuff.

One way to get around this is to make sure that you always do the same
"OS_END_FAULT_HANDLER" bit before calling omni_thread::exit().  A less
error-prone solution is to define a class which derives from omni_thread, and
to do your extra bits in the constructor and destructor of that derived class.
The destructor of this class will be called even when the thread exits by
calling omni_thread::exit().

However, note that the constructor of a derived class will be invoked by the
thread that creates it, not by the created thread itself.  If it is necessary
for the created thread itself to call something, this must be done in the
run() or run_undetached() member functions.  The destructor will be called by
the thread itself in the case of a detached thread, and by the joining thread
in the case of an undetached thread.



Tristan

+--------------------------------------------------------------------+
|  Tristan Richardson                 Email:  tjr@orl.co.uk          |
|  ORL                                  Tel:  +44 1223 343000        |
|  24a Trumpington Street               Fax:  +44 1223 313542        |
|  Cambridge, CB2 1QA, UK               WWW:  http://www.orl.co.uk/  |
+--------------------------------------------------------------------+
|          ORL - The Olivetti & Oracle Research Laboratory           |
+--------------------------------------------------------------------+