From: Jens Maurer (Jens.Maurer_at_[hidden])
Date: 2001-09-17 15:46:09
William Kempf wrote:
> >If you do switch to boost/cstdint.hpp, you need to be aware of
> >the std -> boost namespace change for the int_fastXX_t (or uintXX_t
> >or whatever) types. So the places in the source code where you
> >use these typedefs need syntactic adaptations to account for
> >the namespace change.
> The types were used in only one place, and I didn't qualify the namespace at
> all (an error if they are part of std::, but my compiler didn't complain, go
> figure). Since they are used inside of a boost:: namespace I shouldn't have
> to qualify them, should I?
No, you shouldn't. And the regression tests will tell if we
> >Let me start with a bit of explanation:
> Oh, I understood this, and the same is true when using the Win32 API.
The "explanation" was more for the general boost audience than
for you in particular. I just wanted to make sure everybody had
a chance to understand the issue, since my previous mail was
obviously a bit too short. ;-)
> >While developing a work-around, I wondered why call_once() doesn't
> >take a function object? (This is more a request for adding rationale
> >than for changing the implementation.)
> Because you'd have a race condition. You have to construct a function
> object, and if you could do that in a thread safe manner there'd be no need
> for call_once() ;).
I may be able to construct the function object more than once from different
threads, but still I may want the target function to be called only once.
Anyway, that "once" business seems to be mostly superfluous anyway, because
you can consider your "once" function a monitor, set a flag upon first entry
and skip the function on subsequent entries -> one mutex per "once"
function and a "flag" and you're done.
> An interesting solution. I can clean this up some. There's no need to use
> pthread_once to init the mutex since POSIX defines static initialization of
While static initialization shows up in my Linux "man" page, I'm not
sure whether this is a universal POSIX feature. But I assume you
have the specs available and checked this.
> >> >"tss.cpp", line 134: error: argument of type "void (*)(void *)" is
> >> > incompatible with parameter of type "void (*)(void *) C"
> >> > int res = pthread_key_create(&m_key, cleanup);
> >> > ^
> Probably, but I can't see a clean method of doing so. Probably just
> "writers block" but everything I can come up with uses dynamic memory and
> requires a lot more overhead for all operations. If I have to go that route
> I guess I have to, but I was hoping there was a solution I wasn't thinking
I don't see an obvious solution without dynamic memory allocation,
either: You need to call the proper C++ cleanup handler for each
type T, and this must be routed through an "extern C" wrapper.
Either you have lots of wrappers (one for each type T), which you
cannot find distinct names for (because they're all "extern C"), or
you only have one wrapper and then need to demultiplex into the proper
C++ cleanup handler. Which means you have to store its address
somewhere. However, that address isn't thread-specific, it's
actually global (it's a function address), so it's not really
appropriate to store it in the TSS area.
Could you use a separate, global <map> to map each data pointer
(each of the pointers stored via "set") to its cleanup
function pointer? This incurs only overhead on "set" (and
cleanup), but not on "get", unlike other approaches. I'd
expect "set" to be rare compared to "get".
(Of course, access to the <map> needs to be synchronized, or
needs to be in thread-local storage, similar to the "Windows"
(Btw, please mark the "tss" constructor "explicit". Also, you don't
need the default argument "=0" of the tss constructor, it appears.)
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk