Sample code that shows how to create threads using MFC declares the thread function as both static and __cdecl
. Why is the latter required? Boost threads don't bother with this convention, so is it just an anachronism?
For example (MFC):
static __cdecl UINT MyFunc(LPVOID pParam)
{
...
}
CWinThread* pThread = AfxBeginThread(MyFunc, ...);
Whereas Boost:
static void func()
{
...
}
boost::thread t;
t.create(&func);
(the code samples might not be 100% correct as I am nowhere near an IDE).
What is the point of __cdecl? How does it help when creating threads?
__cdecl is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code.
The cdecl (C Declaration) calling convention is usually the default calling convention for x86 C compilers.
pthread_t is the data type used to uniquely identify a thread. It is returned by pthread_create() and used by the application in function calls that require a thread identifier. The thread is created running start_routine, with arg as the only argument.
The pthread_create() function starts a new thread in the calling process. The new thread starts execution by invoking start_routine(); arg is passed as the sole argument of start_routine().
__cdecl tells the compiler to use the C calling convention (as opposed to the stdcall, fastcall or whatever other calling convention your compiler supports). I believe, VC++ uses stdcall by default.
The calling convention affects things such as how arguments are pushed onto the stack (or registers, in the case of fastcall) and who pops arguments off the stack (caller or callee).
In the case of Boost. I believe it uses template specialization to figure out the appropriate function type and calling convention.
Look at the prototype for AfxBeginThread()
:
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
AFX_THREADPROC
is a typedef for UINT(AFX_CDECL*)(LPVOID)
. When you pass a function to AfxBeginThread()
, it must match that prototype, including the calling convention.
The MSDN pages on __cdecl
and __stdcall
(as well as __fastcall
and __thiscall
) explain the pros and cons of each calling convention.
The boost::thread
constructor uses templates to allow you to pass a function pointer or callable function object, so it doesn't have the same restrictions as MFC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With