Boost logo

Boost Users :

Subject: Re: [Boost-users] [boost][sync?] "Distributed" value (or something...)
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2014-07-29 22:45:04


On 30/07/2014 07:44, Klaim - Joël Lamotte wrote:
> I would like to ask Boost developers and users:
>
> 1. Am I the only one seeing the following pattern in my concurrent
> systems code?
> 2. Is there already some tools available in Boost that does what I
> describe here and that I am not aware of?
> 3. If not, would there be any interest in the tool I'm describing here
> or not? Is it a dumb idea?
> (I keep getting back to this idea but I'm surprised not finding
> anything similar online)
>
>
> The pattern that I am seeing occurs when:
> 1. I have a value or a set of values in an object or several objects
> which value(s) describe some kind of configuration that several other
> systems will read and use.
> 2. The object(s) will be updated only by one thread (at a time).
> 3. When the object's value is modified, all the systems that rely on
> the object's value have to be notified
> so that they update themselves using that value.
> 4. The systems I am refering to can use different threads for updating
> and we can assume that they are running concurrently.
> 5. It is not important that the source object's value is synched with
> the reader's values at all time,
> however it is important that the sequence of changes to the source
> object's value is signaled to the readers
> exactly in the same order and "as fast as possible", but delay is ok.

This sort of thing is a publisher-subscriber model. There are lots of
different implementations of it, depending on what each end "knows" (eg.
push vs. pull) and who you want to have responsible for copying the
data, whether you want lock-based or lock-free, etc.

A really simple (albeit heavy-handed) way of doing this lock-free (or
almost lock-free, depending on shared_ptr implementation) is to have
your data in a shared_ptr; whenever something wants to act on the data
it uses atomic_load to fetch it from some well-known location and can
then do whatever read-only access it wishes; when it wants to change the
data it first copies the entire object, makes the changes in the copy,
and then uses atomic_compare_exchange to replace the "real" version. If
the compare fails, it lost the race to a faster writer so must perform
its updates again on the new data and try exchanging again.

But that pattern is only good for fairly self-contained objects where
reads are frequent and writes are rare, and where it's relatively easy
to copy, throw away and recalculate (which also implies
self-containment, because that gets more complex if you want to act on
two or more such objects). In particular it is *not* suited to frequent
concurrent writes because it's vulnerable to writer starvation (*some*
writer will always succeed, but it's possible that one writer always
fails because a faster one always beats it).

There are other patterns that are better suited to other kinds of
accesses; it's hard to find something generally applicable without
making performance compromises.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net