On Wed, Jul 30, 2014 at 4:45 AM, Gavin Lambert
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.
Thanks for the keywords.
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.
This would work I guess but not well with big values (like a big struct). Also, from my understanding, having one "copy" of the object for each subscriber seems to be potentially more efficient if you already know that each subscriber work with it's own thread (or set of threads). As I assumed and you are confirming, there is a lot of ways to do it depending on the actual context... I guess I should implement a solution with my current case before considering generalization.
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).
Yes, it's exactly for this kind of case. In particular, values being considered as "global configuration", in my case. That is, they are read once from a file at startup, then put in some structs and separate objects. Then, if one is changed, a lot of things have to be updated, but in a lot of different systems running in different threads. So even if the config changes are rare, they might trigger a lot of reaction, and I want the reactions to be independant (which is why I was considering having a copy of the value for each subscriber).
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.
Indeed. In my use case, performance manipulating that value is not really important except on the reactions of the subscriber. I will try some experimental implementations, see how it goes. However I have no experience in measuring speed of a concurrent system, so I'll focus first on interface.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users