?
Solved

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

Posted on 2003-02-24
10
Medium Priority
?
401 Views
Last Modified: 2007-12-19
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
0
Comment
Question by:octi
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
10 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 8007421
Use CreateEvent.
0
 

Author Comment

by:octi
ID: 8007585
This is not working. Is the same as CreateSemaphore.
Thanks,
Octi
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 8007613
Show your code:
1) Creating event
2) Wait function
3) Signal event in other thread
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:octi
ID: 8007670
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
 

Expert Comment

by:BabuPrasanna
ID: 8007753
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
 
LVL 48

Expert Comment

by:AlexFM
ID: 8007824
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
 

Author Comment

by:octi
ID: 8007912
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
 

Author Comment

by:octi
ID: 8007990
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
 
LVL 48

Accepted Solution

by:
AlexFM earned 400 total points
ID: 8008021
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
 

Author Comment

by:octi
ID: 8008209
Hi,

This is working. Thanks very much! The problem was the event processing of the UI thread that produced the deadlock.
Octi
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
Suggested Courses

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question