Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

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

Posted on 2003-02-24
10
Medium Priority
?
416 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
  • 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
Industry Leaders: 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

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Article by: evilrix
Looking for a way to avoid searching through large data sets for data that doesn't exist? A Bloom Filter might be what you need. This data structure is a probabilistic filter that allows you to avoid unnecessary searches when you know the data defin…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

581 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