Make a function to lock until result is available in C++ Builder

I would like to make a function to lock until a certain event is triggered.
The point is that I'm sending some data to a socket and the reception is done asynchronously by a socket receiver thread. When the result is available, onReceive() function of my class is called by the thread.

I would like my sending function to return only when the result is available, meaning that onReceive is called.

I tried to create am object (using CreateSemaphore) and use the WaitForSingleObject method to wait until the object becomes signaled. The onReceive method should set the object's state to signeld, but this is not happening and my function will deadlock.
Any solutions?
Thanks,
Octi
octiAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AlexFMCommented:
Use CreateEvent.
0
octiAuthor Commented:
This is not working. Is the same as CreateSemaphore.
Thanks,
Octi
0
AlexFMCommented:
Show your code:
1) Creating event
2) Wait function
3) Signal event in other thread
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

octiAuthor Commented:
Here is the code sample:

//---------------------------------------------------------------------------
__fastcall CClientConnection::CClientConnection(AnsiString serverAddress, int serverPort)
{
        _hSemaphore = CreateEvent(NULL, false, false, NULL);
        _clientSocket = new CClientSocket(NULL);
        _clientSocket->Address = serverAddress;
        _clientSocket->Port = (short)serverPort;
        _clientSocket->OnReceive = onReceive;
        _clientSocket->Active = true;
}
//---------------------------------------------------------------------------this method should lock until a result is available
CResponseMessage* __fastcall CClientConnection::sendRequest(CRequestMessage* requestMessage)
{
        AnsiString result = requestMessage->parseMessage();
        if (_clientSocket->SendText(result) != result.Length())
        {
                return NULL;
        }
        Block();
        //make a copy of the received message and return  
        CMessage* message = new CMessage(_message);
        return (CResponseMessage*)message;
}
//---------------------------------------------------------------------------this method is called by the reader thread---------
void __fastcall CClientConnection::onReceive(TComponent* Owner, AnsiString text)
{
        _message->addString(text);
        if (_message->isComplete())
        {
                 Unblock();
        }
}
//---------------------------------------------------------------------------
void __fastcall CClientConnection::Block()
{
        WaitForSingleObject(_hSemaphore, INFINITE);
}
//---------------------------------------------------------------------------
void __fastcall CClientConnection::Unblock()
{
        SetEvent(_hSemaphore);
}
0
BabuPrasannaCommented:
Use the following functions properly,

CreateSemaphore()
WaitForSingleObject()
ReleaseSemaphore()

You must CreateSemaphore()in the main thread

RelaseSemaphore() after calling the onRecieve()

And in Send() you must call WaitForSingleObject() and then signal and return.

Initial count is set to 0
0
AlexFMCommented:
Looks OK. I try to imagine a situation when such code doesn't work, and can think only about two things:

1) Unblock is never called

2) Thread which is waiting for event cannot process other messages (this applies only for the threads with message queue).

What is the thread context of sendRequest function? If this is UI thread (for example, main thread), this can cause deadlock.
0
octiAuthor Commented:
AlexFM>

Hi,

It seem's than Unblock is not called, but the reason is the deadlock. The sendRequest method is called from a OnButtonClick() method of a Form. I suppose this is an UI thread.
What could be the reason of deadlock for such a thread? Thanks,
Octi
0
octiAuthor Commented:
AlexFM>

Hi,

It seem's than Unblock is not called, but the reason is the deadlock. The sendRequest method is called from a OnButtonClick() method of a Form. I suppose this is an UI thread.
What could be the reason of deadlock for such a thread? Thanks,
Octi
0
AlexFMCommented:
The reason of deadlock is:
Main thread is waiting for event. At this time it gets some message (for example, WM_PAINT or any other). If this message is sent and not posted, SendMessage doesn't return because it is not handled (thread is waiting).
Main thread (or any UI thread) should never wait with INFINITE parameter.

You can wait by such way only in worker thread, and instead of using WaitForSingleObject you should use WaitForMultipleObjects. Array of objects should always contain thread stop event (this allows to stop thread in any time).

Other way: waiting with processing messages. To do this you need to use WaitForMultipleObjectsEx or use such code fragment (written in Microsoft VC++, translate it to C++ Builder):

// waiting for event and processing messages
while ( TRUE )
{
    dwResult = WaitForSingleObject(hEvent, 100);

    if ( dwResult == WAIT_OBJECT_0 )
    {
         // OK
         break;
    }

    // process thread messages and wait again
    DoEvents();
}

void DoEvents()
{
    MSG msg;
   
    while ( ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE ) )
    {  
        if ( ::GetMessage(&msg, NULL, 0, 0))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        else
        {
            break;
        }
    }
}

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
octiAuthor Commented:
Hi,

This is working. Thanks very much! The problem was the event processing of the UI thread that produced the deadlock.
Octi
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.