Re: gthread-win32.c



On Tue, 22 May 2001, Steven Brooks wrote:

> Sebastian Wilhelmi wrote:
>
> > Hi Kaz, Dan, Steven and all interested parties.
> >
> > We now have a native thread implementation for win32. Everything was quite
> > straightforward once I got used to the different calling conventions in
> > windows (Argh....!). The only challange were the condition varibales. They are
> > modelled after what Kaz proposed, I think it's called "Explicit Notification".
> > Using GArrays instead of GLists they should be quite efficient....
> >
> > Please have a look to avoid any loopholes in this implementation.
> >
> > http://cvs.gnome.org/bonsai/cvsblame.cgi?file=glib/gthread/gthread-win32.c
> >
> > Thanks,
> > Sebastian
> >
>
> 234                if (retval == WAIT_TIMEOUT)
> 235                  {
> 236                    EnterCriticalSection (&cond->lock);

Beware that EnterCriticalSection can throw a low memory structured
exception, if it needs to allocate the internal auto-reset event
and the CreateEvent() fails. As a hack, it's possible to create an
auto-reset event, and store its handle into the critical section.
Been there, done that. On NT4 there is a variant called
InitializeCriticalSectionAndSpincount which will preallocate
the event if the spincount is 0x80000000 - 0x7FFFFFFF.

> 237                    g_ptr_array_remove (cond->array, event);
> 238
> 239                    /* In the meantime we could have been signaled,
> so we must again
> 240                     * wait for the signal, this time with no
> timeout, to reset it */
> 241                    win32_check_for_error (WAIT_FAILED !=
> WaitForSingleObject (event, 0));
> 242
> 243                    LeaveCriticalSection (&cond->lock);
> 244                  }
>
> Should this not change retval?  If the object has been signalled, then
> it should return successful.  Otherwise, the event which caused the
> object to be signalled is lost.

Absolutely.  There are two requirements: one is that if a timeout and
signal happen about the same time, we want to make sure everything is
in a sane state. Then there is a secondary requirement that it would be
nice if the timeout would avoid ``eating'' the signal, because the
signal is more important. You can dispense with the second requirement,
but then the application programmer must treat every timeout as a
potential signal: record that the timeout happened, then re-test
the predicate and do what is necessary, then act on the timeout.

>
> 462                retval->thread = (HANDLE) _beginthreadex (NULL,
> stack_size, g_thread_proxy,
> 463 wilhelmi 1.1 retval, 0, &ignore);
>
> Interesting.  Why not use CreateThread?

Because _beginthreadex uses CreateThread to routes your thread through
an internal threading function which sets up and cleans up
thread-specific storage related to Microsoft's C library. The cleanup
happens when your thread terminates by returning from its threading
function. But what if two separate libraries want to attach thread
specific storage to a thread?

It's all because of Microsoft's brain-damaged thread local storage
implementation, which doesn't have destructor functions unlike the
POSIX one. In the POSIX world, your software component can attach
thread-specific data to a thread without the need to override the
thread startup function. When the thread terminates, a registered
handler associated with the thread specific key will be invoked which
can clean up the thread specific resources. So a large number of
program modules can independently attach thread specific resources to a
thread.





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]