views:

36

answers:

1

I have to share a BLOB in a multithreaded application and and I'm currently looking into shared_ptr/weak_ptr approach, but I'm not exactly sure it is correct.

There is a worker thread that creates a resource class (new CResource). CResource can be quite large, so I want to avoid extra copies.

Then there is another UI thread, I want to PostMessage with pointer to CResource to.

But the worker thread can exit faster than UI thread or vice versa. And worker has no way to know if the message has been processed.

So I'm wondering if I can create a (new shared_ptr) in worker thread, and then pass a (new weak_ptr) to postmessage function, and, if it will take a care of automatic cleanup. So, if worker thread destroys it's shared_ptr, the UI thread will return false on weak_ptr.lock, therefore there would be no need for extra synchronization and resource management.

Also what will happen if worker creates a new CResource, UI thread starts running, worker calls shared_ptr.reset(new CResource)? It seems UI thread can start reading deleted data at this point if no locking is made?

Or what if the main thread exits, and deletes it's shared_ptr during the cleanup, is the weak_ptr going to be dangling?

I'm kinda new to all this shared/weak_ptr thing, and the documentation is a little bit confusing for me for now, so excuse me if it's a dumb question.

I would be grateful if someone could tell me if it's worth investigating this option, or if there are multiple pitfalls and some old school approach is better?

+1  A: 

weak_ptr is typically used to break cycles in interdependent data structures.

I believe from the description you provided that this will work. Once weak_ptr::lock succeeds, you are good until you let the returned shared_ptr go out of scope.

I don't understand why you don't just give the UI thread a shared_ptr of its own, though. Then you don't have to worry about the shared_ptr in the worker thread disappearing and taking your BLOB access with it. Data sharing like this is precisely what shared_ptr is ideal for.

Steve Townsend
Well, if the main thread has done executing the pointer is pretty much expired, so skipping the update is alright. The question is how weak_ptr will know that there is no shared_ptr anymore, as it's been deleted with all the refcounted data it had. I can't find anything solid about weak_ptr thread safety.
Madman
The reset scenario also gets more confusing the more I think about it. Basically two threads have a shared_ptr's ponting to resource A, thread a .get()'s raw pointer and caches it for local access, thread B .reset()'s the shared_ptr, thread A reads the .get()'ted pointer - 0x80000005?
Madman
@Madman - yes, if you use `shared_ptr` like that it will fault. What you should do instead if have a `shared_ptr<workitem>` that is used by both threads, where each lets it go out of scope when they are done. Create a brand-new `shared_ptr` to hold each workitem - don't use `reset()` in a single global `shared_ptr`.
Steve Townsend
Actually, from my experiments it seems that reset() works just fine. If there are multiple shared_pointers to object, you create a weak_ptr, then reset one of the shared_ptr references, the weak_ptr and other shared_ptr's will still point to original object, but the reset'ed pointer will point to new object. If you had only 1 shared_ptr reference, then weak_ptr will get invalidated as soon as it leaves scope or is deleted. Works even better than I expected. Although couldn't find documentation on this behavior. The get() is also completely safe if you have a shared_ptr in scope.
Madman
@Madman - I did not know it worked like that, thanks for the follow-up info. I guess you can post this as an answer and credit yourself by accepting it :-)
Steve Townsend
I'm a little concerned that this might be the "undefined behavior" or vs2010 specific. But if it's the intended behavior then it's simply great.
Madman
@Madman - FYI I saw a comment elsewhere on SO today (from trusted source) that calling `reset()` does not affect other `shared_ptr`'s with the same object - just the one that you `reset`.
Steve Townsend