kakush
kakush

Reputation: 3484

EnterCriticalSection and CRITICAL_SECTION on windows

In my const' - I want that 'secondCommand' will be called only after 'firstCommand'. I tried to work with EnterCriticalSection, but the problem is, where to initiate my lock - If I do it in the constructor (at #), and release the lock after 'firstCommand'( at ##), and try to acquire the lock again before 'secondCommand' (at ###), it might not work since at ###, even if the lock is locked - secondCommand can still be called - since the the locking accured in the same thead (it is just like calling two times in a row "lock" and "lock" - there will not be a deadlock).

on the other hand, If I lock right before 'firstCommand' (at ####) and release right after 'firstCommand' (at ##), when checking if the lock is locked - the lock can uninitialized - which will cause a problem. here is my code:

myClass::myClass (){
    #
    threadFunction();
    ###
    secondCommand();
}

void myClass::threadFunction(){
    DWORD threadID;
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadFunc,0, 0, &threadID);
}

threadFunc(){
    ####
    firstCommand();
    ##
    while(true){};
}

It seems like an easy problem, but I've been tring to solve it for an hour now.Can anyone help ?

Upvotes: 1

Views: 563

Answers (2)

Roger Rowland
Roger Rowland

Reputation: 26259

Maybe the nature of your problem is not as simple as the example you posted, but one obvious way is just to do this

myClass::myClass (){
    firstCommand();
    threadFunction();
    secondCommand();
}

void myClass::threadFunction(){
    DWORD threadID;
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadFunc,0, 0, &threadID);
}

threadFunc(){
    while(true){};
}

Is there some reason that firstCommand has to run on another thread?

EDIT
As you need to run firstCommand on the background thread, then use an event to signal when it's safe. So in myClass define a member variable (or somewhere accessible to both threads) for an event handle

HANDLE m_hEvent;

and use it like so

myClass::myClass (){
    m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    threadFunction();
    WaitForSingleObject(m_hEvent, INFINITE);
    secondCommand();
    CloseHandle(m_hEvent);
    m_hEvent = NULL;
}

void myClass::threadFunction(){
    DWORD threadID;
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadFunc,0, 0, &threadID);
}

threadFunc(){
    firstCommand();
    SetEvent(m_hEvent);
    while(true){};
}

So, in the main thread, secondCommand waits for the event to be signalled before running. In the worker thread, the event is set (signalled) after firstCommand has completed.

Upvotes: 1

Taylor Brandstetter
Taylor Brandstetter

Reputation: 3623

I think you'd be better off using an event: look at CreateEvent, SetEvent and WaitForSingleObject

You would create the event in the constructor, wait for it at "###", and set it at "##". And you should probably check the return value of WaitForSingleObject; it will be WAIT_OBJECT_0 if successful.

Upvotes: 2

Related Questions