Boost logo

Boost :

From: Johan Nilsson (johan.nilsson_at_[hidden])
Date: 2004-07-30 06:03:41


"John Maddock" <john_at_[hidden]> wrote in message
news:020001c4755b$7dfad200$33570352_at_fuji...
> > > I agree, and it should be able to clean up non-boost threads as well -
> > > consider what happens if you're writing a library, and not a program -

[snip]

> >
> > How can you ever be sure the c-runtime will behave correctly when
> > these are not available/initialized for your thread (note you did never
> call _beginthread!).
>
> I agree violently that the calling thread must have been started with
> __beginthread. I can't think of any threading lib where this is not the
> case - even exception handling doesn't work in a thread unless it was
> created with __beginthread. This is very different however from requiring
> that the thread was created with Boost.Threads, which is what was being
> suggested.
>

I was also always under the same impression, but reading the MSDN docs on
CreateThread it sounds a bit less restrictive than I remembered:

"A thread in an executable that is linked to the static C run-time library
(CRT) should use _beginthread and _endthread for thread management rather
than CreateThread and ExitThread. Failure to do so results in small memory
leaks when the thread calls ExitThread. Another work around is to link the
executable to the CRT in a DLL instead of the static CRT. Note that this
memory leak only occurs from a DLL if the DLL is linked to the static CRT
and a thread calls the DisableThreadLibraryCalls function. Otherwise, it is
safe to call CreateThread and ExitThread from a thread in a DLL that links
to the static CRT."

Also, in what way doesn't exception handling work if the thread wasn't
created using __beginthread? I tried the following snippet under WinXP/VC7.1
which ran silently (yes, under debug config):

--
#include <cassert>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
DWORD WINAPI ThreadFn(void*)
{
  struct local : std::exception
  {
    local(bool* p_dtor_called)
     : _p_dtor_called(p_dtor_called)
   { *_p_dtor_called = false; }
    ~local()
    { *_p_dtor_called = true; }
    bool* _p_dtor_called;
  };
  bool dtor_called = false;
  try
  {
      local l(&dtor_called);
      throw std::logic_error("test");
  }
  catch (std::exception& e)
  {
    assert(dtor_called);
    return 0;
 }
  assert(false);
  return 1;
}
int main(int, char*[])
{
  HANDLE h = CreateThread(NULL, 0, &ThreadFn, NULL, 0, NULL);
  WaitForSingleObject(h, INFINITE);
  return 0;
}
--
I don't pretend that I understand all subtleties of exception handling, but
the above at least _seems_ to work ok.
// Johan

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk