comp.lang.ada
 help / color / mirror / Atom feed
* C++ primer on multithreading
@ 2011-04-20 10:45 Alex R. Mosteo
  2011-04-20 11:23 ` Peter C. Chapin
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Alex R. Mosteo @ 2011-04-20 10:45 UTC (permalink / raw)


I know there are some proficient C++ people here. Hope you can help me.

I need to do some multi-threading stuff, in the sense that I will need the 
equivalent of a protected object with some conditional blocking entries.

I'm a bit rusty on my C++, so I wonder what would be the best approach to 
this. Things that I know that exist, but that I have not mastered: pthreads, 
ACE, boost.

Thank you for your suggestions.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 10:45 C++ primer on multithreading Alex R. Mosteo
@ 2011-04-20 11:23 ` Peter C. Chapin
  2011-04-20 13:06   ` Alex R. Mosteo
  2011-04-20 11:32 ` Dmitry A. Kazakov
  2011-04-20 12:00 ` Maciej Sobczak
  2 siblings, 1 reply; 16+ messages in thread
From: Peter C. Chapin @ 2011-04-20 11:23 UTC (permalink / raw)


On Wed, 20 Apr 2011 12:45:22 +0200, "Alex R. Mosteo"
<alejandro@mosteo.invalid> wrote:

>I'm a bit rusty on my C++, so I wonder what would be the best approach to 
>this. Things that I know that exist, but that I have not mastered: pthreads, 
>ACE, boost.

There may be an advantage in looking at Boost Threads. The new C++ standard
contains thread support in its library that bears a close resemblance to
Boost Threads.

Peter



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 10:45 C++ primer on multithreading Alex R. Mosteo
  2011-04-20 11:23 ` Peter C. Chapin
@ 2011-04-20 11:32 ` Dmitry A. Kazakov
  2011-04-20 12:00 ` Maciej Sobczak
  2 siblings, 0 replies; 16+ messages in thread
From: Dmitry A. Kazakov @ 2011-04-20 11:32 UTC (permalink / raw)


On Wed, 20 Apr 2011 12:45:22 +0200, Alex R. Mosteo wrote:

> I know there are some proficient C++ people here. Hope you can help me.
> 
> I need to do some multi-threading stuff, in the sense that I will need the 
> equivalent of a protected object with some conditional blocking entries.

Equivalent of an entry is an event+queue combination. Threads are queued to
the entry. Upon an evaluation of the barrier the first thread from the
queue gets its event signalled and then removed from the queue.
Alternatively to the events one can suspend/resume caller's thread.

Implementation of Ada's entries is quite a challenge in C++, and this
technique is largely unknown to C++ people. Usually they just hang a mutex
on the procedures of some object. This is roughly an equivalent of Ada's
protected procedure (not entry). An entry cannot be emulated this way
without busy waiting or else periodical polling. Sometimes sets of mutexes
are used with single object to avoid busy waiting, but this is a very
dangerous technique vulnerable to deadlocking.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 10:45 C++ primer on multithreading Alex R. Mosteo
  2011-04-20 11:23 ` Peter C. Chapin
  2011-04-20 11:32 ` Dmitry A. Kazakov
@ 2011-04-20 12:00 ` Maciej Sobczak
  2011-04-20 13:04   ` Alex R. Mosteo
  2 siblings, 1 reply; 16+ messages in thread
From: Maciej Sobczak @ 2011-04-20 12:00 UTC (permalink / raw)


On Apr 20, 12:45 pm, "Alex R. Mosteo" <alejan...@mosteo.invalid>
wrote:

> I need to do some multi-threading stuff, in the sense that I will need the
> equivalent of a protected object with some conditional blocking entries.

This is not enough. What are you going to do with these entries? How
many threads will use the same entry? How many entries will be used at
a time by a single thread?

If you don't try to reimplement the Ada semantics in full (select
statement, requeue, anyone? :-) ), then conditional variables are
sufficient to implement typical multithreading patterns - this can be
nicely encapsulated by the "protected object" interface.

Boost is a good quality wrapper for system services and therefore
useful for portability, but brings a whole lot of dependencies with it
- it might or might not be of concern.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 12:00 ` Maciej Sobczak
@ 2011-04-20 13:04   ` Alex R. Mosteo
  2011-04-20 14:34     ` Georg Bauhaus
                       ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Alex R. Mosteo @ 2011-04-20 13:04 UTC (permalink / raw)


Maciej Sobczak wrote:

> On Apr 20, 12:45 pm, "Alex R. Mosteo" <alejan...@mosteo.invalid>
> wrote:
> 
>> I need to do some multi-threading stuff, in the sense that I will need
>> the equivalent of a protected object with some conditional blocking
>> entries.
> 
> This is not enough. What are you going to do with these entries? How
> many threads will use the same entry? How many entries will be used at
> a time by a single thread?

Not many threads involved, and I have been really not very explicit. 
Basically I need a protected queue with blocking semantics; several 
writters, one consumer.

Also more generally, I wondered too if there's some ready-to-use protected 
stuff in C++ that spares me dealing with mutexes to emulate a synchronized 
interface.

> If you don't try to reimplement the Ada semantics in full (select
> statement, requeue, anyone? :-) ), then conditional variables are
> sufficient to implement typical multithreading patterns - this can be
> nicely encapsulated by the "protected object" interface.

No, I don't want the full boat :) Also I wouldn't want to fall in the 
inverse trap of what's so frequently touted here of writing C in Ada. So any 
pointers on what are considered best practices nowadays in C++ for 
multithreading are welcome too.

> Boost is a good quality wrapper for system services and therefore
> useful for portability, but brings a whole lot of dependencies with it
> - it might or might not be of concern.

That's no problem. I will be using stock debian systems, so as long as it's 
there...

Alex.

> 
> --
> Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 11:23 ` Peter C. Chapin
@ 2011-04-20 13:06   ` Alex R. Mosteo
  0 siblings, 0 replies; 16+ messages in thread
From: Alex R. Mosteo @ 2011-04-20 13:06 UTC (permalink / raw)


Peter C.  Chapin wrote:

> On Wed, 20 Apr 2011 12:45:22 +0200, "Alex R. Mosteo"
> <alejandro@mosteo.invalid> wrote:
> 
>>I'm a bit rusty on my C++, so I wonder what would be the best approach to
>>this. Things that I know that exist, but that I have not mastered:
>>pthreads, ACE, boost.
> 
> There may be an advantage in looking at Boost Threads. The new C++
> standard contains thread support in its library that bears a close
> resemblance to Boost Threads.

I have even read in some random forum that Boost will be in the next C++ 
standard...



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 13:04   ` Alex R. Mosteo
@ 2011-04-20 14:34     ` Georg Bauhaus
  2011-04-20 20:44     ` Maciej Sobczak
  2011-04-21  6:58     ` Dmitry A. Kazakov
  2 siblings, 0 replies; 16+ messages in thread
From: Georg Bauhaus @ 2011-04-20 14:34 UTC (permalink / raw)


On 20.04.11 15:04, Alex R. Mosteo wrote:

> Also more generally, I wondered too if there's some ready-to-use protected 
> stuff in C++ that spares me dealing with mutexes to emulate a synchronized 
> interface.

Just now, by coincidence, Emmanuel Stapf has announced a new beta
of Eiffel Studio.

"The highlight of the 6.8 release is the support of the SCOOP mechanism."

Which stands for Simple Concurrent Object-Oriented Programming.

Seems to have taken quite some efforts to fill old Eiffel's keyword
"separate" with life. :-)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 13:04   ` Alex R. Mosteo
  2011-04-20 14:34     ` Georg Bauhaus
@ 2011-04-20 20:44     ` Maciej Sobczak
  2011-04-21  8:50       ` Alex R. Mosteo
  2011-04-21  6:58     ` Dmitry A. Kazakov
  2 siblings, 1 reply; 16+ messages in thread
From: Maciej Sobczak @ 2011-04-20 20:44 UTC (permalink / raw)


On Apr 20, 3:04 pm, "Alex R. Mosteo" <alejan...@mosteo.invalid> wrote:

> Basically I need a protected queue with blocking semantics; several
> writters, one consumer.

This is easy to implement and for the above you will need only one
mutex and one condvar.

This is what I have quickly found on Google:

http://www.quantnet.com/cplusplus-multithreading-boost/

See especially 18.11, but I guess the whole page is worth reading.

> Also more generally, I wondered too if there's some ready-to-use protected
> stuff in C++ that spares me dealing with mutexes to emulate a synchronized
> interface.

No and the (current) C++ culture is that this stuff is supported by
libraries, not by language. As you see with the code on the above
page, it might not be as elegant as in Ada, but still not that
terribly difficult to grasp.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 13:04   ` Alex R. Mosteo
  2011-04-20 14:34     ` Georg Bauhaus
  2011-04-20 20:44     ` Maciej Sobczak
@ 2011-04-21  6:58     ` Dmitry A. Kazakov
  2011-04-21 21:03       ` Maciej Sobczak
  2 siblings, 1 reply; 16+ messages in thread
From: Dmitry A. Kazakov @ 2011-04-21  6:58 UTC (permalink / raw)


On Wed, 20 Apr 2011 15:04:06 +0200, Alex R. Mosteo wrote:

> Basically I need a protected queue with blocking semantics; several 
> writters, one consumer.

That is just one mutex + one manual-reset event.
 
An interesting issue is the producer's behavior when the queue is full. I
presume it would fail or the queue may grow infinitely (:-)) You may need
an additional pulse event to handle this more reasonably.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-20 20:44     ` Maciej Sobczak
@ 2011-04-21  8:50       ` Alex R. Mosteo
  0 siblings, 0 replies; 16+ messages in thread
From: Alex R. Mosteo @ 2011-04-21  8:50 UTC (permalink / raw)


Maciej Sobczak wrote:

> On Apr 20, 3:04 pm, "Alex R. Mosteo" <alejan...@mosteo.invalid> wrote:
> 
>> Basically I need a protected queue with blocking semantics; several
>> writters, one consumer.
> 
> This is easy to implement and for the above you will need only one
> mutex and one condvar.
> 
> This is what I have quickly found on Google:
> 
> http://www.quantnet.com/cplusplus-multithreading-boost/
> 
> See especially 18.11, but I guess the whole page is worth reading.

I'll do, thanks.

> 
>> Also more generally, I wondered too if there's some ready-to-use
>> protected stuff in C++ that spares me dealing with mutexes to emulate a
>> synchronized interface.
> 
> No and the (current) C++ culture is that this stuff is supported by
> libraries, not by language. As you see with the code on the above
> page, it might not be as elegant as in Ada, but still not that
> terribly difficult to grasp.

Boost is it then. Thanks to everyone!

Alex.

> 
> --
> Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-21  6:58     ` Dmitry A. Kazakov
@ 2011-04-21 21:03       ` Maciej Sobczak
  2011-04-22  8:38         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 16+ messages in thread
From: Maciej Sobczak @ 2011-04-21 21:03 UTC (permalink / raw)


On Apr 21, 8:58 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> An interesting issue is the producer's behavior when the queue is full. I
> presume it would fail

Or block. Being full is symmetric to being empty (hint: being full
means that you run out of empty space, which means that the reserve of
empty space is... empty :-) ).

> or the queue may grow infinitely (:-))

There are no infinite computers yet. You will get the out of memory
condition, which in C++ is reported with an exception. This is handled
cleanly: mutex will be automatically unlocked and consumers will not
be affected.

> You may need
> an additional pulse event to handle this more reasonably.

What "pulse event"? They are not needed at all.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-21 21:03       ` Maciej Sobczak
@ 2011-04-22  8:38         ` Dmitry A. Kazakov
  2011-04-22 21:45           ` Maciej Sobczak
  0 siblings, 1 reply; 16+ messages in thread
From: Dmitry A. Kazakov @ 2011-04-22  8:38 UTC (permalink / raw)


On Thu, 21 Apr 2011 14:03:20 -0700 (PDT), Maciej Sobczak wrote:

> On Apr 21, 8:58�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> An interesting issue is the producer's behavior when the queue is full. I
>> presume it would fail
> 
> Or block. Being full is symmetric to being empty (hint: being full
> means that you run out of empty space, which means that the reserve of
> empty space is... empty :-) ).
> 
>> or the queue may grow infinitely (:-))
> 
> There are no infinite computers yet. You will get the out of memory
> condition, which in C++ is reported with an exception. This is handled
> cleanly: mutex will be automatically unlocked and consumers will not
> be affected.

Real-life implementations of n-to-1 queue I made, wait for a finite time
(typical response time limit 1-2s) and then throw an exception (e.g.
BusyFault). This is an equivalent of timed entry call in Ada. The queue may
grows up to a certain limit. 

>> You may need
>> an additional pulse event to handle this more reasonably.
> 
> What "pulse event"? They are not needed at all.

Pulse event is an event reset automatically after notification all waiting
threads. It can be used to unblock queueing threads which then start
grabbing the mutex. The event is set when the consumer removes an item from
the queue. Since pulse events are race condition exposed, certain care must
be taken.

BTW, there is no big difference on a single-core, but on a multi-core this
design compared to Ada's protected objects is still a bit wasting, because
producer threads may be really concurrent. An Ada implementation may just
release the first blocked producer without activating the whole clique.

In general multi-core threading is more fragile and has more "interesting"
issues than single-core. We keep on detecting some minor glitches in our
C++ software.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-22  8:38         ` Dmitry A. Kazakov
@ 2011-04-22 21:45           ` Maciej Sobczak
  2011-04-23  6:51             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 16+ messages in thread
From: Maciej Sobczak @ 2011-04-22 21:45 UTC (permalink / raw)


On Apr 22, 10:38 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> > What "pulse event"? They are not needed at all.
>
> Pulse event is an event reset automatically after notification all waiting
> threads.

That's why they are not needed here. After putting new item to the
queue (or removing one item - as already said, these are symmetric
problems), you need to wake up only one waiting thread, not all of
them.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-22 21:45           ` Maciej Sobczak
@ 2011-04-23  6:51             ` Dmitry A. Kazakov
  2011-04-23 21:35               ` Maciej Sobczak
  0 siblings, 1 reply; 16+ messages in thread
From: Dmitry A. Kazakov @ 2011-04-23  6:51 UTC (permalink / raw)


On Fri, 22 Apr 2011 14:45:02 -0700 (PDT), Maciej Sobczak wrote:

> On Apr 22, 10:38�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>>> What "pulse event"? They are not needed at all.
>>
>> Pulse event is an event reset automatically after notification all waiting
>> threads.
> 
> That's why they are not needed here. After putting new item to the
> queue (or removing one item - as already said, these are symmetric
> problems), you need to wake up only one waiting thread, not all of
> them.

For that you need a queue of threads rather than or additionally to the
queue of items and resume/suspend method instead of events. This is a
different approach, which I had difficulties with.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-23  6:51             ` Dmitry A. Kazakov
@ 2011-04-23 21:35               ` Maciej Sobczak
  2011-04-24  7:42                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 16+ messages in thread
From: Maciej Sobczak @ 2011-04-23 21:35 UTC (permalink / raw)


On Apr 23, 8:51 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> For that you need a queue of threads

This queue is already part of system-level implementation of condition
variables and there is no need to implement it at the user level.
The code example I have pointed previously uses the notify_one()
function to wake up only one waiting thread.

--
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: C++ primer on multithreading
  2011-04-23 21:35               ` Maciej Sobczak
@ 2011-04-24  7:42                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 16+ messages in thread
From: Dmitry A. Kazakov @ 2011-04-24  7:42 UTC (permalink / raw)


On Sat, 23 Apr 2011 14:35:02 -0700 (PDT), Maciej Sobczak wrote:

> On Apr 23, 8:51�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> For that you need a queue of threads
> 
> This queue is already part of system-level implementation of condition
> variables and there is no need to implement it at the user level.

Event-based implementations have advantages of their own. E.g. thread queue
when used must be sorted by thread priorities and/or queueing time. One
frequently must wait for multiple events: "can queue" or "timed out" or
"can read from file" or "must exist'.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-04-24  7:42 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-20 10:45 C++ primer on multithreading Alex R. Mosteo
2011-04-20 11:23 ` Peter C. Chapin
2011-04-20 13:06   ` Alex R. Mosteo
2011-04-20 11:32 ` Dmitry A. Kazakov
2011-04-20 12:00 ` Maciej Sobczak
2011-04-20 13:04   ` Alex R. Mosteo
2011-04-20 14:34     ` Georg Bauhaus
2011-04-20 20:44     ` Maciej Sobczak
2011-04-21  8:50       ` Alex R. Mosteo
2011-04-21  6:58     ` Dmitry A. Kazakov
2011-04-21 21:03       ` Maciej Sobczak
2011-04-22  8:38         ` Dmitry A. Kazakov
2011-04-22 21:45           ` Maciej Sobczak
2011-04-23  6:51             ` Dmitry A. Kazakov
2011-04-23 21:35               ` Maciej Sobczak
2011-04-24  7:42                 ` Dmitry A. Kazakov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox