开发者

how to use postThreadMessage to pass a struct

I want to use windows's message queue facilities to 开发者_开发技巧send a struct to another thread. But I find out that the postthreadmessage function only provide two integer parameters, lparam and wparam for me to pass arguments.So I decide to put the address of the struct in lparam. Is this the correct way windows use to pass struct?

And I intend to use boost::shared_ptr to hold the address of struct in both the receiver thread and sender thread. I doubt that when the two shared_ptrs goes out of scope, will the struct be freed twice? I can not figure out a way to ensure the struct allocated on heap will be 100% freed, Any ideas?


To the first question, yes, LPARAM is intended to be used as an integer or a pointer. That is clear from the definition:

typedef LONG_PTR LPARAM;

That is an integer long enough to hold a pointer.

About the shared_ptr thing, you are right, if you pass the raw pointer and wrap it into another shared_ptr you will free it twice:

shared_ptr<Thing> a;
PostThreadMessage(x, 0, (LPARAM)a.get());
...
LRESULT OnMessage(int msg, WPARAM wp, LPARAM lp)
{
    shared_ptr<Thing> p((Thing*)lp); //Bad!!!
}

But you can try this workaround instead:

shared_ptr<Thing> a;
PostThreadMessage(x, 0, new shared_ptr<Thing>(a)); //pointer to smart-pointer
...
LRESULT OnMessage(int msg, WPARAM wp, LPARAM lp)
{
    shared_ptr<Thing> *pp = (shared_ptr<Thing>*)lp;
    shared_ptr<Thing> p(*pp);
    delete pp; //no leak
}

AFTERTHOUGHT: Note that PostThreadMessage may fail... and you don't want to leak a shared_ptr.

In my experience it is generally better to use a std::deque to hold the data and use the PostThreadMessage to notify that there is data there. In this way you'll never lose an object! YMMV


I've come across a similar situation using the Qt QModelIndex class, which holds data using a void*, but I manage the data it's pointing to using shared_ptr.

To avoid dereferencing the void* directly, which may be pointing to a no longer existing object, I use a map from void* to weak_ptr. All the objects that are referenced by QModelIndexes are stored in the map. When time comes to dereference a void*, I use the void* as a key to retrieve the corresponding weak_ptr from the map, then convert the weak_ptr into a shared_ptr. The shared_ptr is then either equal to the void* or it is NULL, and you get type safety as well.

Note that my solution did not have to deal with the concurrency issues that you mention, but you may be able to adapt it to your situation. You could use the lparam to store the raw pointer to your object, and then use the map to convert from a raw to a smart pointer. Protect the map with a mutex and you may be there.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜