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