我想使用Windows的消息队列设施发送一个结构到另一个线程。 但是我发现postthreadmessage函数只提供了两个整数参数,lparam和wparam来传递参数。所以我决定把结构地址放在lparam中。 这是正确的方式Windows使用传递结构?
我打算使用boost :: shared_ptr在接收者线程和发送者线程中保存struct的地址。 我怀疑,当两个shared_ptrs超出范围,结构将被释放两次? 我想不出一种方法来确保分配在堆上的结构将被100%释放,任何想法?
对于第一个问题,是的,LPARAM旨在用作整数或指针。 从定义中可以明显看出:
typedef LONG_PTR LPARAM;
这是一个足够容纳一个指针的整数。
关于shared_ptr的东西,你是对的,如果你传递原始指针并将其包装到另一个shared_ptr中,你将释放它两次:
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!!! }
但是你可以尝试这个解决方法:
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 }
事后 :请注意,PostThreadMessage可能会失败…并且你不想泄漏一个shared_ptr。
根据我的经验,通常最好使用std :: deque来保存数据,并使用PostThreadMessage来通知那里有数据。 这样你永远不会失去一个对象! 因人而异
我遇到过使用Qt QModelIndex
类的类似情况,它使用void*
保存数据,但是我使用shared_ptr
管理指向它的数据。
为了避免直接取消引用void*
,这可能指向不再存在的对象,我使用从void*
到weak_ptr
的映射。 所有由QModelIndexes
引用的对象都存储在地图中。 当需要解引用void*
,我使用void*
作为key来从map中检索相应的weak_ptr
,然后将weak_ptr
转换成shared_ptr
。 然后shared_ptr
或者等于void*
或者它是NULL
,并且你也可以获得类型安全性。
请注意,我的解决方案不必处理您提到的并发问题,但是您可能可以根据自己的情况进行调整。 您可以使用lparam将原始指针存储到您的对象,然后使用映射将原始指针转换为智能指针。 用互斥体保护地图,你可能在那里。