Intel® C++ Compiler 16.0 User and Reference Guide
The Microsoft Foundation Classes (MFC) library depends upon thread local storage to map from its class wrappers to the GDI handles for objects. Because an Intel® Cilk™ Plus strand is not guaranteed to run on any specific OS thread, parallel code using Intel® Cilk™ Plus cannot safely call MFC functions.
There are two methods typically used to perform a computationally-intensive task in an MFC-based application:
The user interface (UI) thread creates a computation thread to run the computationally-intensive task. The compute thread posts messages to the UI thread to update it, leaving the UI thread free to respond to UI requests.
The computationally-intensive code is run on the UI thread, updating the UI directly and occasionally running a "message pump" to handle other UI requests.
Since the runtime system can switch operating system threads, Intel® Cilk™ Plus code must be isolated from code such as MFC that depends on Thread Local Storage.
To add a computation thread to an MFC program:
Create a computation thread using operating-system facilities (_beginthreadex or AfxBeginThread). All the C++ code that is to be converted to Intel® Cilk™ Plus should run in this thread. The computation thread leaves the main (UI) thread available to run the message pump for processing window messages and updating the UI.
Pass the handle (HWND) for the UI windows to the computation thread. When the computation thread needs to update the UI, it should send a message to the UI thread by calling PostMessage. PostMessage marshals and queues the message into the message queue associated with the thread that created the window handle. Do not use SendMessage. SendMessage is run on the currently executing thread, which is not the correct (UI) thread.
Test the C++ program to ensure that the logic and thread management are correct.
Add Intel® Cilk™ Plus constructs to the logic in the computation thread.
Before terminating, the main (UI) thread should wait for the computation thread to complete, using WaitForSingleObject().
The QuickDemo sample program, supplied with the product, illustrates an Intel® Cilk™ Plus application using MFC.
Additional recommendations:
When the main UI thread creates the computation thread, it should not wait for the thread to complete. The function that creates the computation thread should return to allow the message pump to run.
Be sure that none of the data passed to the computation thread is allocated on the stack. If it is, it will quickly be invalidated as the computation-thread creation function returns, releasing the data.
A data block passed to the computation thread should be freed by the computation thread when it is done, just before it sends a completion message to the UI.
Use the PostMessage function instead of CWnd::PostMessage, as a primary reason for creating a computation thread is to avoid the MFC thread-local variables in Intel® Cilk™ Plus code.
A (short) computation using Intel® Cilk™ Plus constructs can be called directly from the UI thread, as long as the computation behaves as a "black box" and does not attempt to communicate with the message pump or any other threads. This feature allows you to call non-interactive functions without regard to whether they use Intel® Cilk™ Plus.