Search code examples
windowsboostmessage-queueshared-ptr

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?


Solution

  • 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