Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
696 views
in Technique[技术] by (71.8m points)

c++ - Thread safe vector

Let me start by saying that I have read most SO and other topics on the subject.

The way I understand things, std::vector will reallocate memory when pushing back new items, which is my case, unless I have reserved enough space (which is not my case).

What I have is a vector of std::shared_ptr, and that vector holds unique objects (or more correctly, pointers to unique objects in the vector).

The handling of those objects via pointers is wrapped around a Factory & Handler class, but pointers to the objects are accessible from outside the wrapper class and can have member values modified. There is no deleting happening at any time.

If I am understanding correctly issues raised in previous SO questions about std::vector and thread safety, adding (push_back) new objects may invalidate previous pointers, as the vector internally may reallocate memory and copy everything over, which would of course be a disaster for me.

My intentions are to read from that vector, often modifying objects through the pointers, and add new items to the vector, from threads running asynchronously.

So,

  1. Using atomic or mutexes is not enough? If I push back from one thread, another thread handling an object via pointer may end up having an invalid object?
  2. Is there a library that can handle this form of MT issues? The one I keep reading about is Intel's TBB, but since I'm already using C++11, I'd love to keep changes to a minimum, even if it means more work on my part - I want to learn in the process, not just copy-paste.
  3. Other than locking access while modifying objects, I would want asynchronous parallel read access to the vector that will not be invalidated by push_backs. How can I achieve that?

If it is of any importance, all the above is on linux (debian jessie) using gcc-4.8 with c++11 enabled.

I am open to using minimally invasive libraries.

Many thanks in advance :-)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

adding (push_back) new objects may invalidate previous pointers ...

No, this operation doesn't invalidate any previous pointers, unless you are refering to addresses inside the vectors internal data management (which clearly isn't your scenario).
If you store raw pointers, or std::shared_ptr's there, those will be simply copied, and not get invalid.


As mentioned in comments a std::vector isn't very suitable to guarantee thread safety for producer / consumer patterns for a number of reasons. Neither storing raw pointers to reference the alive instances is!

A Queue will be much better to support this. As for standards you can use the std::deque to have ceratain access points (front(),back()) for the producer / consumer.

To make these access point's thread safe (for pushing/popping values) you can easily wrap them with your own class and use a mutex along, to secure insertion/deletion operations on the shared queue reference.
The other (and major, as from your question) point is: manage ownership and lifetime of the contained/referenced instances. You may also transfer ownership to the consumer, if that's suitable for your use case (thus getting off from the overhead with e.g. std::unique_ptr), see below ...

Additionally you may have a semaphore (condition variable), to notify the consumer thread, that new data is available.


'1. Using atomic or mutexes is not enough? If I push back from one thread, another thread handling an object via pointer may end up having an invalid object?'

The lifetime (and thus thread safe use) of the instances stored to the queue (shared container) need's to be managed separately (e.g. using smart pointers like std::shared_ptr or std::unique_ptr stored there).

'2. Is there a library ...'

It can be achieved all well with the existing standard library mechanisms IMHO.

As for point 3. see what's written above. As what I can tell further about this, it sounds like you're asking for something like a rw_lock mutex. You may provide a surrogate for this with a suitable condition variable.

Feel free to ask for more clarification ...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...