[thread] A few submissions

Hi, I would like to propose the following components for inclusion into Boost.Thread: 1. Once-blocks. This is a flavor of the "once" concept. One can define a block of code that should be executed only once, like that: void foo() { BOOST_LOG_ONCE_BLOCK() { puts("Hello, world once!"); } } The code within the block can access names (e.g. variables) as if it was a usual code block. Why not call_once: * The once-code is defined in-place, which greatly simplifies usage in many cases. One of the main goals of the "once" concept is the dynamic initialization, which involves the variables being initialized. With once-blocks there is no need bind these variables into a functor. Once-blocks are also easier to be used within a macro. * The resulting code is much shorter since the thread synchronization code is separated from the once-code. call_once is instantiated with each once-functor, although the synchronization code is the same. * The once-flag is smaller on Windows. In fact, unlike call_once, the behavior on Windows is equivalent to POSIX. * It has ticket #4225 fixed. If this component is accepted, I would also like to port call_once to once-blocks. Source code: <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/boost/log/utility/once_block.hpp> <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/libs/log/src/once_block.cpp> 2. Lightweight read/write mutex. Basically, I want a portable analogue for pthread_rwlock_t, with minimum dependencies, code size and memory footprint. Naturally, it is compatible with Boost.Thread locks. Why not shared_mutex: * shared_mutex.hpp depends on a lot of other headers. It brings in a great deal of Boost.DateTime, although I don't need the timed methods at all. * It offers more than I ever use. I don't need upgradeability. * It is larger than pthread_rwlock_t on POSIX systems (on Linux x64 it's 192 bytes vs 56). On Windows NT 6 it can be implemented through SRWLOCK, which is of size of one pointer. * I remember there were reports that shared_mutex is slower than pthread_rwlock_t. But I haven't done testing, so I won't press it. Source code: <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/boost/log/detail/light_rw_mutex.hpp> <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/libs/log/src/light_rw_mutex.cpp> 3. Lightweight thread-local storage for small POD values. Allows to store POD values of size up to sizeof(void*) with least possible overhead, memory and performance-vise. thread_specific< int > tls; Why not thread_specific_ptr: * thread_specific_ptr performance depends on the total number of ptrs within the application as it involves an additional lookup among them on access. thread_local does nothing more than abstracting away the native API for TLS, so it provides better performance. * thread_specific_ptr requires to dynamically allocate memory even for tiniest things, like bool or int. This is inconvenient and awkward, especially when memory and exception safety matters. <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/boost/log/detail/thread_specific.hpp> <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/libs/log/src/thread_specific.cpp> A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration. 4. shared_lock_guard. A light analogue to shared_lock, which allows to generate a more efficient code. Ticket #3567. Source code: <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/boost/log/detail/locks.hpp> As a part of this addition I would like to improve segregation of boost/thread/locks.hpp by extracting every component within it into a separate header in a new "locks" directory. 5. The strictest_lock metafunction. Given the list of lock types, it selects the one that offers the strictest concurrency guarantees (i.e. shared lock is stricter than no lock at all, exclusive lock is stricter than shared lock). This metafunction can be useful in generic code, where the final lock type must be deduced. Source code: <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/boost/log/utility/strictest_lock.hpp> I understand that some of these tools might seem specific to my case, but I think they could be useful in general. If any of these tools is accepted into Boost.Thread, the code is not set in stone - namings and implementation details can be changed, if needed. I can do the code transition, write docs and a few tests, if needed. Just let me know if either of these is of interest and whether I am allowed to do so. PS: If you want SVN access to all these things, it is available on the SourceForge: <http://sourceforge.net/scm/?type=svn&group_id=199644>

----- Original Message ----- From: "Andrey Semashev" <andrey.semashev@gmail.com> To: <boost@lists.boost.org> Sent: Sunday, July 04, 2010 7:15 PM Subject: [boost] [thread] A few submissions
Hi,
I would like to propose the following components for inclusion into Boost.Thread:
1. Once-blocks. This is a flavor of the "once" concept. One can define a block of code that should be executed only once, like that:
void foo() { BOOST_LOG_ONCE_BLOCK() { puts("Hello, world once!"); } }
The code within the block can access names (e.g. variables) as if it was a usual code block.
I like this construction. What about renaming it BOOST_ONCE?
Why not call_once:
* The once-code is defined in-place, which greatly simplifies usage in many cases. One of the main goals of the "once" concept is the dynamic initialization, which involves the variables being initialized. With once-blocks there is no need bind these variables into a functor. Once-blocks are also easier to be used within a macro. * The resulting code is much shorter since the thread synchronization code is separated from the once-code. call_once is instantiated with each once-functor, although the synchronization code is the same. * The once-flag is smaller on Windows. In fact, unlike call_once, the behavior on Windows is equivalent to POSIX. * It has ticket #4225 fixed.
Could you explain how do you ensure that the code is thread safe?
2. Lightweight read/write mutex. Basically, I want a portable analogue for pthread_rwlock_t, with minimum dependencies, code size and memory footprint. Naturally, it is compatible with Boost.Thread locks.
Why not shared_mutex:
* shared_mutex.hpp depends on a lot of other headers. It brings in a great deal of Boost.DateTime, although I don't need the timed methods at all.
I consider the timed functions a must to have. What about making it depend on Boost.Chrono instead?
* It offers more than I ever use. I don't need upgradeability.
pthread_rwlock_t are upgradable. Is there any constraint to don't make your Lightweight read/write mutex upgradable?
3. Lightweight thread-local storage for small POD values. Allows to store POD values of size up to sizeof(void*) with least possible overhead, memory and performance-vise.
thread_specific< int > tls;
Why not thread_specific_ptr:
* thread_specific_ptr performance depends on the total number of ptrs within the application as it involves an additional lookup among them on access. thread_local does nothing more than abstracting away the native API for TLS, so it provides better performance. * thread_specific_ptr requires to dynamically allocate memory even for tiniest things, like bool or int. This is inconvenient and awkward, especially when memory and exception safety matters.
<http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/boost/log/detail/thread_specific.hpp> <http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/libs/log/src/thread_specific.cpp>
A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
4. shared_lock_guard. A light analogue to shared_lock, which allows to generate a more efficient code. Ticket #3567.
As a part of this addition I would like to improve segregation of boost/thread/locks.hpp by extracting every component within it into a separate header in a new "locks" directory.
+1 for the separation. This should help to limit the dependencies.
5. The strictest_lock metafunction. Given the list of lock types, it selects the one that offers the strictest concurrency guarantees (i.e. shared lock is stricter than no lock at all, exclusive lock is stricter than shared lock). This metafunction can be useful in generic code, where the final lock type must be deduced.
Could you show a usage example?
I understand that some of these tools might seem specific to my case, but I think they could be useful in general. If any of these tools is accepted into Boost.Thread, the code is not set in stone - namings and implementation details can be changed, if needed. I can do the code transition, write docs and a few tests, if needed. Just let me know if either of these is of interest and whether I am allowed to do so.
I'm interesteed. Why don't request a mini-review of the proposed features as a Boost.Thread extension? Most of the synchronization features should work as well for interprocess. What about including all the synchronization features in a separated Synchro library? Best, Vicente

Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
I use a static_thread_specific_ptr in namespace detail because I only needed static TSS, but I don't propose adding this as a public interface to boost. a better implementation of the existing thread_specific_ptr interface can be almost as efficient as static_thread_specific_ptr. there is one additional indirection (two in the prototype implementation), but it is just as efficient as thread_local otherwise. static_thread_specific_ptr: https://svn.boost.org/svn/boost/sandbox/transaction/boost/transact/detail/st... efficient thread_specific_ptr prototype: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=tss.hpp&directory=& pretty severe bug it also fixes: https://svn.boost.org/trac/boost/ticket/3837

On 05.07.2010 0:11, Stefan Strasser wrote:
Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
I use a static_thread_specific_ptr in namespace detail because I only needed static TSS, but I don't propose adding this as a public interface to boost. a better implementation of the existing thread_specific_ptr interface can be almost as efficient as static_thread_specific_ptr. there is one additional indirection (two in the prototype implementation), but it is just as efficient as thread_local otherwise.
How do you work around the problem with delay loaded dlls?

Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
a better implementation of the existing thread_specific_ptr interface can be almost as efficient as static_thread_specific_ptr. there is one additional indirection (two in the prototype implementation), but it is just as efficient as thread_local otherwise.
How do you work around the problem with delay loaded dlls?
I don't. I suppose platforms that have that problem can be supported by hiding the TLS vector behind a function call, or if the platform doesn't support global TLS but supports TLS that is local to the DLL the pointer to the TLS vector could be obtained under a mutex lock for each module. note that this implementation only uses one TLS variable. if it can't be supported you'd have to fall back to TlsAlloc etc. I think this rather obscure use case should not punish most use cases. Vicente has performed some performance tests of Boost.Transact (that uses static_thread_specific_ptr) on different platforms, some supporting TLS, some don't. IIRC it is pretty much unusable on platforms that don't.

On 05.07.2010 0:58, Stefan Strasser wrote:
How do you work around the problem with delay loaded dlls?
I don't. I suppose platforms that have that problem can be supported by hiding the TLS vector behind a function call, or if the platform doesn't support global TLS but supports TLS that is local to the DLL the pointer to the TLS vector could be obtained under a mutex lock for each module. note that this implementation only uses one TLS variable. if it can't be supported you'd have to fall back to TlsAlloc etc.
AFAIK, Windows prior to Vista and Linux have this issue. It's a quite wide range of platforms, IMHO.
I think this rather obscure use case should not punish most use cases. Vicente has performed some performance tests of Boost.Transact (that uses static_thread_specific_ptr) on different platforms, some supporting TLS, some don't.
Well, I thought the same when I implemented the same technique in Boost.Log. I was considered otherwise when I got lots of complaints from users. Apparently, the "delay-loaded dll" is not so uncommon as it may seem. My point is that, unless it "just works", the use of this feature should be optional and disabled by default (which effectively means, disabled in 95% of cases). No matter how sad it is. :(

Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
On 05.07.2010 0:58, Stefan Strasser wrote:
How do you work around the problem with delay loaded dlls?
I don't. I suppose platforms that have that problem can be supported by hiding the TLS vector behind a function call, or if the platform doesn't support global TLS but supports TLS that is local to the DLL the pointer to the TLS vector could be obtained under a mutex lock for each module. note that this implementation only uses one TLS variable. if it can't be supported you'd have to fall back to TlsAlloc etc.
AFAIK, Windows prior to Vista and Linux have this issue. It's a quite wide range of platforms, IMHO.
I'm not too familiar with delay-loading, but why can't these platforms be supported by hiding the TLS-access behind a function call so it always originates from the same module?
Well, I thought the same when I implemented the same technique in Boost.Log. I was considered otherwise when I got lots of complaints from users. Apparently, the "delay-loaded dll" is not so uncommon as it may seem. My point is that, unless it "just works", the use of this feature should be optional and disabled by default
in that case, I guess I am suggesting to add a public interface like static_thread_specific_ptr, to support the semantics of __declspec(thread)/__thread/thread_local, i.e. crash when used from delay-loaded modules on platforms that don't support it. it isn't simply a #define because they have different semantics regarding construction/destruction, and types that are support. the final interface could support other POD types besides pointers though.

On 05.07.2010 2:03, Stefan Strasser wrote:
Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
On 05.07.2010 0:58, Stefan Strasser wrote:
How do you work around the problem with delay loaded dlls?
I don't. I suppose platforms that have that problem can be supported by hiding the TLS vector behind a function call, or if the platform doesn't support global TLS but supports TLS that is local to the DLL the pointer to the TLS vector could be obtained under a mutex lock for each module. note that this implementation only uses one TLS variable. if it can't be supported you'd have to fall back to TlsAlloc etc.
AFAIK, Windows prior to Vista and Linux have this issue. It's a quite wide range of platforms, IMHO.
I'm not too familiar with delay-loading, but why can't these platforms be supported by hiding the TLS-access behind a function call so it always originates from the same module?
I'm not sure I understand how it helps. Could you elaborate? The main problem is that you can't guarantee that _any_ boost module is linked with the main executable. Therefore, you can't define a module that would define these compiler-TLS variables.
in that case, I guess I am suggesting to add a public interface like static_thread_specific_ptr, to support the semantics of __declspec(thread)/__thread/thread_local, i.e. crash when used from delay-loaded modules on platforms that don't support it.
That is a different extension from what I am proposing. But frankly speaking, I don't see much use from it if it crashes on some setups and I can't detect such setups in my code that uses this component.

Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
I'm not too familiar with delay-loading, but why can't these platforms be supported by hiding the TLS-access behind a function call so it always originates from the same module?
I'm not sure I understand how it helps. Could you elaborate?
I assumed an executable linked against boost.
in that case, I guess I am suggesting to add a public interface like static_thread_specific_ptr, to support the semantics of __declspec(thread)/__thread/thread_local, i.e. crash when used from delay-loaded modules on platforms that don't support it.
That is a different extension from what I am proposing. But frankly speaking, I don't see much use from it if it crashes on some setups and I can't detect such setups in my code that uses this component.
I could reply to this in terms of content, but this is easier: what you're saying by that is that declspec(thread)/... make no sense on platforms that don't support delay-loading with static TSS, and was/will never be used. that's obviously not the case. right now boost offers a platform independent interface to TlsAlloc/..., but not to declspec(thread)/...

On 07/05/2010 11:17 AM, Stefan Strasser wrote:
Zitat von Andrey Semashev <andrey.semashev@gmail.com>:
in that case, I guess I am suggesting to add a public interface like static_thread_specific_ptr, to support the semantics of __declspec(thread)/__thread/thread_local, i.e. crash when used from delay-loaded modules on platforms that don't support it.
That is a different extension from what I am proposing. But frankly speaking, I don't see much use from it if it crashes on some setups and I can't detect such setups in my code that uses this component.
I could reply to this in terms of content, but this is easier: what you're saying by that is that declspec(thread)/... make no sense on platforms that don't support delay-loading with static TSS, and was/will never be used. that's obviously not the case.
What I'm saying is that it makes little use for library writers if it doesn't allow to detect the faulty platforms. Or fallback to explicit API usage on such platforms. But that's getting OT.

1. Once-blocks. This is a flavor of the "once" concept. One can define a block of code that should be executed only once, like that:
void foo() { BOOST_LOG_ONCE_BLOCK() { puts("Hello, world once!"); } }
The code within the block can access names (e.g. variables) as if it was a usual code block.
I like this construction. What about renaming it BOOST_ONCE?
Like I said, I'm not tied with naming.
Could you explain how do you ensure that the code is thread safe?
I run the test multiple times on a multi-core machine. Never failed.
2. Lightweight read/write mutex. Basically, I want a portable analogue for pthread_rwlock_t, with minimum dependencies, code size and memory footprint. Naturally, it is compatible with Boost.Thread locks.
Why not shared_mutex:
* shared_mutex.hpp depends on a lot of other headers. It brings in a great deal of Boost.DateTime, although I don't need the timed methods at all.
I consider the timed functions a must to have.
You can always use shared_mutex. I use timed functions quite rarely.
What about making it depend on Boost.Chrono instead?
1. It's not accepted. 2. I don't think that switching Boost.DateTime to Boost.Chrono does much good in terms of lightness. Remember, one of my goals is to make it extremely cheap to include.
* It offers more than I ever use. I don't need upgradeability.
pthread_rwlock_t are upgradable.
Is it? Through what functions?
Is there any constraint to don't make your Lightweight read/write mutex upgradable?
On Windows NT6 SRWLOCK doesn't support upgrades. And I don't know how to upgrade pthread_rwlock_t.
A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
Please, see my up-front notes, I've already answered. :)
5. The strictest_lock metafunction. Given the list of lock types, it selects the one that offers the strictest concurrency guarantees (i.e. shared lock is stricter than no lock at all, exclusive lock is stricter than shared lock). This metafunction can be useful in generic code, where the final lock type must be deduced.
Could you show a usage example?
typedef shared_lock< shared_mutex > lock1; typedef unique_lock< shared_mutex > lock2; typedef strictest_lock< lock1, lock2 >::type lock3; BOOST_STATIC_ASSERT(is_same< lock2, lock3 >::value);
I understand that some of these tools might seem specific to my case, but I think they could be useful in general. If any of these tools is accepted into Boost.Thread, the code is not set in stone - namings and implementation details can be changed, if needed. I can do the code transition, write docs and a few tests, if needed. Just let me know if either of these is of interest and whether I am allowed to do so.
I'm interesteed. Why don't request a mini-review of the proposed features as a Boost.Thread extension?
Well, I don't know how to do it formally. Consider this a request.
Most of the synchronization features should work as well for interprocess. What about including all the synchronization features in a separated Synchro library?
I don't think that things like once-blocks or rw mutex are relevant to Boost.Interprocess. And I don't see the point of creating a new library for these things. IMO, they fit just fine in Boost.Thread.

----- Original Message ----- From: "Andrey Semashev" <andrey.semashev@gmail.com> To: <boost@lists.boost.org> Sent: Sunday, July 04, 2010 10:26 PM Subject: Re: [boost] [thread] A few submissions
1. Once-blocks. This is a flavor of the "once" concept. One can define a block of code that should be executed only once, like that:
Could you explain how do you ensure that the code is thread safe?
I run the test multiple times on a multi-core machine. Never failed.
Well, this should not be enough. Could you explain what have you do protect from concurrent access?
2. Lightweight read/write mutex. Basically, I want a portable analogue for pthread_rwlock_t, with minimum dependencies, code size and memory footprint. Naturally, it is compatible with Boost.Thread locks.
Why not shared_mutex: * shared_mutex.hpp depends on a lot of other headers. It brings in a great deal of Boost.DateTime, although I don't need the timed methods at all.
I consider the timed functions a must to have.
You can always use shared_mutex. I use timed functions quite rarely.
Well, as you said shared_mutex is not as Lightweight as the user expects.
What about making it depend on Boost.Chrono instead?
1. It's not accepted.
I hope it will be soon.
2. I don't think that switching Boost.DateTime to Boost.Chrono does much good in terms of lightness. Remember, one of my goals is to make it extremely cheap to include.
Why is so important that is be extremely cheap to include? What is important for me is run-time and storage used.
* It offers more than I ever use. I don't need upgradeability.
pthread_rwlock_t are upgradable.
Is it? Through what functions?
If I remeber you just need to tale the mutex for write once it was taken for read. pthread_rwlock_rdlock(mutex); /* upgrade the mutex*/ pthread_rwlock_wrlock(mutex);
Is there any constraint to don't make your Lightweight read/write mutex upgradable?
On Windows NT6 SRWLOCK doesn't support upgrades.
This should be a good reason to don't support upgrades :(
And I don't know how to upgrade pthread_rwlock_t.
A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
Please, see my up-front notes, I've already answered. :)
Do you mean that at the end the C++0x standard will have problems with dynamically-loaded modules? :(
5. The strictest_lock metafunction. Given the list of lock types, it selects the one that offers the strictest concurrency guarantees (i.e. shared lock is stricter than no lock at all, exclusive lock is stricter than shared lock). This metafunction can be useful in generic code, where the final lock type must be deduced.
Could you show a usage example?
typedef shared_lock< shared_mutex > lock1; typedef unique_lock< shared_mutex > lock2; typedef strictest_lock< lock1, lock2 >::type lock3; BOOST_STATIC_ASSERT(is_same< lock2, lock3 >::value);
Sorry, I was not enough clear. Could you show an example on which the lock to be used is the strictest_lock of two locks, a use case if you want?
I understand that some of these tools might seem specific to my case, but I think they could be useful in general. If any of these tools is accepted into Boost.Thread, the code is not set in stone - namings and implementation details can be changed, if needed. I can do the code transition, write docs and a few tests, if needed. Just let me know if either of these is of interest and whether I am allowed to do so.
I'm interesteed. Why don't request a mini-review of the proposed features as a Boost.Thread extension?
Well, I don't know how to do it formally. Consider this a request.
I considere this a request for interest, not a request for a mini-review.
Most of the synchronization features should work as well for interprocess. What about including all the synchronization features in a separated Synchro library?
I don't think that things like once-blocks or rw mutex are relevant to Boost.Interprocess.
once-blocks, no, but why not rw mutexes and shared_lock_guard?
And I don't see the point of creating a new library for these things. IMO, they fit just fine in Boost.Thread.
There is no reason to have two unique_lock, ... If you had to use some generic synchronization mechanisms for process mutexes, will you look at the thread library? Best, Vicente

1. Once-blocks. This is a flavor of the "once" concept. One can define a block of code that should be executed only once, like that:
Could you explain how do you ensure that the code is thread safe?
I run the test multiple times on a multi-core machine. Never failed.
Well, this should not be enough. Could you explain what have you do protect from concurrent access?
The once flag is only modified when an internal mutex is locked. If a thread entered the once-block, all other threads are blocked in a condition variable. Take a look at the code for more details.
You can always use shared_mutex. I use timed functions quite rarely.
Well, as you said shared_mutex is not as Lightweight as the user expects.
That's right. You want more features - you pay with longer compile times.
2. I don't think that switching Boost.DateTime to Boost.Chrono does much good in terms of lightness. Remember, one of my goals is to make it extremely cheap to include.
Why is so important that is be extremely cheap to include? What is important for me is run-time and storage used.
I also want to shorten compile times.
* It offers more than I ever use. I don't need upgradeability.
pthread_rwlock_t are upgradable.
Is it? Through what functions?
If I remeber you just need to tale the mutex for write once it was taken for read.
pthread_rwlock_rdlock(mutex); /* upgrade the mutex*/
pthread_rwlock_wrlock(mutex);
This us undefined behavior: <http://opengroup.org/onlinepubs/007908775/xsh/pthread_rwlock_wrlock.html>
A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
Please, see my up-front notes, I've already answered. :)
Do you mean that at the end the C++0x standard will have problems with dynamically-loaded modules? :(
I mean that current compilers have this problem. Whether the C++0x-conforming implementations will solve it or not is yet to be seen.
Sorry, I was not enough clear. Could you show an example on which the lock to be used is the strictest_lock of two locks, a use case if you want?
I use it in logger features in Boost.Log. Say, we have N features that derive from one another and implement an operation and require a certain concurrency protection. Each feature can require a different protection. template< typename T > struct feature1 : T { typedef typename strictest_lock< typename T::op_lock, shared_lock< ... > >::type op_lock; void op(); // requires shared_lock and calls T::op }; template< typename T > struct feature2 : T { typedef typename strictest_lock< typename T::op_lock, unique_lock< ... > >::type op_lock; void op(); // requires unique_lock and calls T::op }; Now, if we instantiate feature1< feature2< ... > >, the resulting compound will have the op_lock type that satisfies all features.
I'm interesteed. Why don't request a mini-review of the proposed features as a Boost.Thread extension?
Well, I don't know how to do it formally. Consider this a request.
I considere this a request for interest, not a request for a mini-review.
What stops it from being a mini-review?
once-blocks, no, but why not rw mutexes and shared_lock_guard?
rw mutex is process-local and I'd like to keep it that way. Regarding lock types, I have no strong opinion, but I have no problems with using locks from Boost.Thread on any type that models the appropriate concepts.
And I don't see the point of creating a new library for these things. IMO, they fit just fine in Boost.Thread.
There is no reason to have two unique_lock, ... If you had to use some generic synchronization mechanisms for process mutexes, will you look at the thread library?
It's a question of finding the information about the lock types. If Boost.Interprocess docs have a link to Boost.Thread locks, then yes, I would find it.

----- Original Message ----- From: "Andrey Semashev" <andrey.semashev@gmail.com> To: <boost@lists.boost.org> Sent: Sunday, July 04, 2010 11:49 PM Subject: Re: [boost] [thread] A few submissions
1. Once-blocks. This is a flavor of the "once" concept. One can define a block of code that should be executed only once, like that:
Could you explain how do you ensure that the code is thread safe?
I run the test multiple times on a multi-core machine. Never failed.
Well, this should not be enough. Could you explain what have you do protect from concurrent access?
The once flag is only modified when an internal mutex is locked. If a thread entered the once-block, all other threads are blocked in a condition variable. Take a look at the code for more details.
You can always use shared_mutex. I use timed functions quite rarely.
Well, as you said shared_mutex is not as Lightweight as the user expects.
That's right. You want more features - you pay with longer compile times.
2. I don't think that switching Boost.DateTime to Boost.Chrono does much good in terms of lightness. Remember, one of my goals is to make it extremely cheap to include.
Why is so important that is be extremely cheap to include? What is important for me is run-time and storage used.
I also want to shorten compile times.
* It offers more than I ever use. I don't need upgradeability.
pthread_rwlock_t are upgradable.
Is it? Through what functions?
If I remeber you just need to tale the mutex for write once it was taken for read.
pthread_rwlock_rdlock(mutex); /* upgrade the mutex*/
pthread_rwlock_wrlock(mutex);
This us undefined behavior:
<http://opengroup.org/onlinepubs/007908775/xsh/pthread_rwlock_wrlock.html>
Oups. I missed a sentence.
A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
Please, see my up-front notes, I've already answered. :)
Do you mean that at the end the C++0x standard will have problems with dynamically-loaded modules? :(
I mean that current compilers have this problem. Whether the C++0x-conforming implementations will solve it or not is yet to be seen.
Then if I understand your thread_specific class doesn't have any issues with dynamically-loaded modules, isn't it? If this is the case, could you clarify how your class avoids the problem?
Sorry, I was not enough clear. Could you show an example on which the lock to be used is the strictest_lock of two locks, a use case if you want?
I use it in logger features in Boost.Log. Say, we have N features that derive from one another and implement an operation and require a certain concurrency protection. Each feature can require a different protection.
template< typename T > struct feature1 : T { typedef typename strictest_lock< typename T::op_lock, shared_lock< ... > >::type op_lock;
void op(); // requires shared_lock and calls T::op };
template< typename T > struct feature2 : T { typedef typename strictest_lock< typename T::op_lock, unique_lock< ... > >::type op_lock;
void op(); // requires unique_lock and calls T::op };
Now, if we instantiate feature1< feature2< ... > >, the resulting compound will have the op_lock type that satisfies all features.
OK, I see. This seems a valid use case.
I'm interesteed. Why don't request a mini-review of the proposed features as a Boost.Thread extension?
Well, I don't know how to do it formally. Consider this a request.
I considere this a request for interest, not a request for a mini-review.
What stops it from being a mini-review?
packaging, documentation, tests, ... Thanks, Vicente

A few notes up-front. There are extensions in some compilers for TLS support. It offers even better performance and easier to use. Also, C++0x will bring this feature into the language. But: * It is known to have problems with dynamically-loaded modules. * It is not portable. Even when C++0x it out, not all compilers will support it right away. * thread_specific does not require the variable to have a static storage duration.
Stefan Stasser has proposed a stati_thread_specific_ptr (see attached file). What about a static_thread_specific that could be implemented using the C++0x thread_local, when available?
Please, see my up-front notes, I've already answered. :)
Do you mean that at the end the C++0x standard will have problems with dynamically-loaded modules? :(
I mean that current compilers have this problem. Whether the C++0x-conforming implementations will solve it or not is yet to be seen.
Then if I understand your thread_specific class doesn't have any issues with dynamically-loaded modules, isn't it? If this is the case, could you clarify how your class avoids the problem?
It explicitly uses native API (pthread_key_create, TlsAlloc, etc.) to manage TLS slots.
participants (3)
-
Andrey Semashev
-
Stefan Strasser
-
vicente.botet