Re: [boost] [thread] synchronized_value: value and move semantics
On 21/02/13 02:02, Vicente J. Botet Escriba wrote:
Hi,
boost::synchronized_value (not released yet [1][2][3]) is based on [4]. See below part of this paper adapted to the Boost.Thread interface.
Currently boost::synchronized_value is in addition Copyable and Swappable. I was wondering if it is worth adding value and move semantics to synchronized_value. Making it EqualityComparable, LessThanComparable and Movable if the underlying type satisfy these requirements will allow to store them on a Boost.Container/C++11 container.
Do you see something completely wrong with this addition? Has some of you had a need for this? Could you share the context?
Sorry, I'm a bit late to the party and not really answering the question.
I can see the usefulness of synchronized_value for C++03, but not in C++11.
It's just too easy to forget to call the synchronise() member:
boost::synchronized_value
Ben Pope wrote
On 21/02/13 02:02, Vicente J. Botet Escriba wrote:
Hi,
boost::synchronized_value (not released yet [1][2][3]) is based on [4]. See below part of this paper adapted to the Boost.Thread interface.
Currently boost::synchronized_value is in addition Copyable and Swappable. I was wondering if it is worth adding value and move semantics to synchronized_value. Making it EqualityComparable, LessThanComparable and Movable if the underlying type satisfy these requirements will allow to store them on a Boost.Container/C++11 container.
Do you see something completely wrong with this addition? Has some of you had a need for this? Could you share the context?
Sorry, I'm a bit late to the party and not really answering the question.
I can see the usefulness of synchronized_value for C++03, but not in C++11.
Why?
It's just too easy to forget to call the synchronise() member:
boost::synchronized_value<std::queue<int>> synch_queue; if(!synch_queue->empty()) synch_queue->pop();
when was was meant was (excuse use of auto, I've become lazy):
boost::synchronized_value<std::queue<int>> synch_queue; { auto lock = synch_queue.synchronize(); if(!synch_queue->empty()) synch_queue->pop(); }
This is neither safe or efficient (2 lock/unlocks).
this should be boost::synchronized_value<std::queue<int>> synch_queue; { auto lock = synch_queue.synchronize(); if(!lock->empty()) lock->pop(); }
I think this should just not exist in C++11 and instead be replaced by something like monitor <T> described by Herb Sutter [1]:
monitor<std::queue<int>> synch_queue; queue([](std::queue& q) { if(!q.empty()) q.pop(); }
Sorry I don't understand the syntax.
Now we're safe and efficient (one lock/unlock per block).
This was just the intention of synchronize ;-)
Since movability is a C++11 thing, can we have something harder to use incorrectly than synchronized_value for C++11?
Could you elaborate?
I guess my point is rather than C++11ifying synchronized_value, can we have monitor instead?
Thoughts?
Could you summarize here what are the advantages the monitor you are referring to? Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/thread-synchronized-value-value-and-move-... Sent from the Boost - Dev mailing list archive at Nabble.com.
Le 26/06/13 18:03, Vicente Botet a écrit :
Ben Pope wrote
On 21/02/13 02:02, Vicente J. Botet Escriba wrote:
Hi,
boost::synchronized_value (not released yet [1][2][3]) is based on [4]. See below part of this paper adapted to the Boost.Thread interface.
Currently boost::synchronized_value is in addition Copyable and Swappable. I was wondering if it is worth adding value and move semantics to synchronized_value. Making it EqualityComparable, LessThanComparable and Movable if the underlying type satisfy these requirements will allow to store them on a Boost.Container/C++11 container.
Do you see something completely wrong with this addition? Has some of you had a need for this? Could you share the context? Sorry, I'm a bit late to the party and not really answering the question.
I can see the usefulness of synchronized_value for C++03, but not in C++11. Why?
It's just too easy to forget to call the synchronise() member:
boost::synchronized_value<std::queue<int>> synch_queue; if(!synch_queue->empty()) synch_queue->pop();
when was was meant was (excuse use of auto, I've become lazy):
boost::synchronized_value<std::queue<int>> synch_queue; { auto lock = synch_queue.synchronize(); if(!synch_queue->empty()) synch_queue->pop(); }
This is neither safe or efficient (2 lock/unlocks). this should be
boost::synchronized_value<std::queue<int>> synch_queue; { auto lock = synch_queue.synchronize(); if(!lock->empty()) lock->pop(); }
I think this should just not exist in C++11 and instead be replaced by something like monitor <T> described by Herb Sutter [1]:
monitor<std::queue<int>> synch_queue; queue([](std::queue& q) { if(!q.empty()) q.pop(); } Sorry I don't understand the syntax.
After looking at the slides I understand now what it means. I guess you meant sync_queue([](std::queue& q) { if(!q.empty()) q.pop(); } ); I like execute around a function locking pattern, and yes without lambdas this pattern is not practical, so no portable to C++03. Adding the function to synchronized_value would not be too hard. Best, Vicente
On 27/06/13 01:05, Vicente J. Botet Escriba wrote:
Le 26/06/13 18:03, Vicente Botet a écrit :
Ben Pope wrote
I can see the usefulness of synchronized_value for C++03, but not in C++11. Why?
It's just too easy to forget to call the synchronise() member:
boost::synchronized_value<std::queue<int>> synch_queue; if(!synch_queue->empty()) synch_queue->pop();
when was was meant was (excuse use of auto, I've become lazy):
boost::synchronized_value<std::queue<int>> synch_queue; { auto lock = synch_queue.synchronize(); if(!synch_queue->empty()) synch_queue->pop(); }
This is neither safe or efficient (2 lock/unlocks). this should be
boost::synchronized_value<std::queue<int>> synch_queue; { auto lock = synch_queue.synchronize(); if(!lock->empty()) lock->pop(); }
OK, I should have paid more attention to detail, my apologies. I think it's just a little bit too easy to forget to use the stack based lock, especially during code maintenance and moving from one call to more than one call.
I think this should just not exist in C++11 and instead be replaced by something like monitor <T> described by Herb Sutter [1]:
monitor<std::queue<int>> synch_queue; queue([](std::queue& q) { if(!q.empty()) q.pop(); } Sorry I don't understand the syntax.
After looking at the slides I understand now what it means. I guess you meant
sync_queue([](std::queue& q)
{ if(!q.empty()) q.pop(); } );
D'oh! Always compile example code. My bad.
I like execute around a function locking pattern, and yes without lambdas this pattern is not practical, so no portable to C++03. Adding the function to synchronized_value would not be too hard.
I'd settle for that, with a note that's it's preferable in C++11 :) Thanks. Ben
On Wed, Jun 26, 2013 at 12:37 PM, Ben Pope
I think this should just not exist in C++11 and instead be replaced by something like monitor<T> described by Herb Sutter [1]:
I'm using several variants of Monitor in my projects. It don't work well in cases where what you really want is syncrhonization, which happen sometime when the design suggests it. In this case you need a mutex, so synchronized_value helps with that. In my opinion, If the multiple access is a bottleneck in real application, it is very easy to spot with a profiler and modify the code as you pointed. Joel Lamotte
participants (4)
-
Ben Pope
-
Klaim - Joël Lamotte
-
Vicente Botet
-
Vicente J. Botet Escriba