BUG: Unified Event Model (Native) inject empty Lock/Unlock()

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Following is a snap-shot of compiler created code when using UEM, use /Fx:

struct __EventCriticalSectionStub
{
void Lock() {}
void Unlock() {}
};

....

__EventCriticalSectionStub __EventingCS;

__EventingCS.Lock() and __EventingCS.Unlock() is called in several important
section such as __AddEventHandler__XXXX and firing event. But due to the flaw
in __EventCriticalSectionStub, corruption happen when using UEM in
multithread project.


From MSDN: Visual C++ Concepts: Adding Functionality - > Introduction to the
Unified Event Model

"..The model supports single- and multithreaded usage and protects data from
simultaneous multithread access..."


Am I missing something, or Visual C ...oops, I did it again?
 
#define THREAD_COUNT 64
// Comment the following to see the problem
#define EXPLICIT_LOCK


[event_source(native, optimize=speed)]
class CSource
{
public:
__event void Print(LPCTSTR psz);

};


[event_receiver(native)]
class CReceiver
{
private:
#ifdef EXPLICIT_LOCK
CComAutoCriticalSection g_Lock;
#endif

public:
void Hook(CSource* p)
{
__hook(&CSource::Print, p, &CReceiver::Print);
}

void Print(LPCTSTR psz)
{
static TCHAR sz[64] = {0};
#ifdef EXPLICIT_LOCK
g_Lock.Lock();
#endif
::lstrcpy(sz, psz);
for(int i=0; i < ::lstrlen(psz); i++)
_puttch(sz);
::ZeroMemory(sz, sizeof(sz));
#ifdef EXPLICIT_LOCK
g_Lock.Unlock();
#endif
}
};


DWORD WINAPI ThreadProc(LPVOID pParam)
{
CSource* ps = static_cast<CSource*>(pParam);
TCHAR sz[64] = {0};

::wsprintf(sz, _T("Hello World! (%d)\n"), ::GetCurrentThreadId());
::Sleep(rand() % 1000);
__raise ps->Print(sz);
return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h[THREAD_COUNT] = {NULL};
CSource s;
CReceiver r;
r.Hook(&s);

srand((unsigned)time(NULL));
for(int i=0; i < THREAD_COUNT; i++)
h = DefaultThreadTraits::CreateThread(NULL, 0, ThreadProc, &s, 0, NULL);
::WaitForMultipleObjects(THREAD_COUNT, h, TRUE, INFINITE);
for(i=0; i < THREAD_COUNT; i++)
::CloseHandle(h);
return 0;
}
 
Back
Top