SendMessage线程安全

时间:2017-10-10 20:47:19

标签: winapi mfc sendmessage

请考虑以下代码段:

CWnd * wnd = /*...*/;
int integer = 1;
integer = 10;
std::function < void ( ) > fn = [&] ()
{
    assert(integer == 10); // ??? (1)
    integer = 20;
}
wnd->SendMessage(WM_INVOKE_FN, NULL, (LPARAM)&fn);
assert(integer == 20); // ??? (2)

WM_INVOKE_FN处理函数定义如下:

afx_msg LRESULT CTestDlg::OnInvokeFn(WPARAM wParam, LPARAM lParam)
{
    (*(std::function < void () > *) lParam)();
    return 0;
}

问题:上面的代码是否在创建wnd仍为线程安全的线程以外的线程上执行?更具体地说,(1)和/或(2)可能会失败,为什么?

我的推理:

1和2都不会失败。

  1. 我们不知道(我们是吗?)SendMessage实际上是如何实现的。但我们可以(可以吗?)假设函数内部使用内存屏障来确保消息队列始终处于有效状态。因此,fn实际上是在内存屏障之后执行的,如果编译器保留了指令顺序,则会看到integer == 10
  2. SendMessage是外部(User32.dll成员)函数,因此将(LPARAM)&fn作为参数传递是一个可观察的操作(是吗?)(编译器不知道哪个线程将执行fn; integer通过引用捕获,并在fn内访问,禁止将{s}重新排序到integer并调用SendMessage。< / LI>
  3. SendMessage至少阻止调用者线程,直到OnInvokeFn返回。同样,我们可以假设在等待过程中涉及一些内存障碍。因此,在integer == 20返回后SendMessage
  4. 我的证明是否正确?有什么想法吗?

0 个答案:

没有答案