Link to home
Start Free TrialLog in
Avatar of bachra04
bachra04Flag for Canada

asked on

blocking call

I need to implement a class based on a blocking call using pthreads

My class blocks for event coming from the network:

 My class is like that :

EventHandler
{
     public void waitForEvent1(){
       
// blocks waiting for event 1 from the network
   
    }
   
    SendEvent2 ( Event1) {
     
        perform some action based on Event1 and send response

  }

public void WaitForEvent2


.etc
   


I m thinking about implementing a blocking queue , is the right solution ?

How to do that using pThreads ?



}

Thx
Avatar of jkr
jkr
Flag of Germany image

What kind of event are you thinking about, since you wrote "from the network"?
Avatar of bachra04

ASKER

some SIP packets coming from remote end point
one simple solution I have in mind is to use a blocking queue :

so my method will be :

BlockingQueue _queue;

public void WaitForMyEvent ()
{
    Event event;
    _queue.Get ( event);
   
  //  take some action based on the contents of the event

}

My Blocking queue is something like in  the following example :

Blocking Queue with PThread

This may do the job, but I need some advice from the experts about a better solution or more refined one.

Thanks.
Linux has always had the poll and select system calls to enable i/o multiplexing without the need for multiple threads. Microsoft never had that (except select for sockets only, if you really read the documentation carefully) so they now push dumbed-down multithreading as a solution (is your background MS by the way?).
Nowadays I would use poll. select has to be there to implement the BSD socket interface but I find poll easier to use. For documentation, see
man 2 poll
man 2 select
a call which might block forever isn't a good design even if you move it to a thread.

if your main thread would like to exit, you would (need to) kill the blocking thread what could cause lossing resources or - worse - data corruption (depending on os and what the thread does when handling data).

so i would support duncan_roe's comment that multi-threading is not necessarily a solution though you could have multi-threading and nevertheless avoid blocking calls.

the easiest way to avoid blocking probably is to make the socket non-blocking. if you do so, any call to read from socket would return immediately and the return value would tell whether the read was successful or has failed. in case of failing (what is almost every time the case if you do the read call in a loop) you would check a global error (errno on linux, WSAGetLastError() on windows) whether the failing was because of avoiding blocking only (EWOULDBLOCK). you then would repeat the call in periods (polling) until you get a success.

You don't need a separate thread for that. you very well could do the periodical read in a idle time if for example you were running a message pump (ui). but an own thread which does nothing but reading from non-blocking socket and sends a message to the main thread on success is a clean and reasonable design pattern. you would have a little timeout between the reads (in order to take the load off the cpu) and would make the thread stoppable from the main thread in the pauses.

there is a similar design possible when using select (as mentioned from duncan_roe). i would prefer select over poll even if it is not quite so convenient to make your code portable. when using select you would let the socket blockable but before any read from the socket you would call select with a timeout argument to check whether the socket "has" any data. the select call would break with success when there is data or would break with failure when the time-out has expired. so you could implement the same design as described with non-blockable sockets by simply avoiding reads when there is no data to read.

Sara
I m using this design for testing purposes , writing test cases and not for production. That's why I don't think it is too bad. The other thing is that I m not dealing directly with a socket. I m using a stack that manages the transport layer.
My problem is how to build my own queue data structure or use an existing one.
ASKER CERTIFIED SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I have found a link to something that I can use.

http://stackoverflow.com/questions/4577961/pthread-synchronized-blocking-queue

Can any one give me a sample code on how to use this queue since I m not very familiar with C coding ?

Thanks
I eventually get it working. now I want to get the blocking call executed inside a separate thread ( in order not to block other parts of the program), any help on how to do that using pthread ?

Thanks
you create the thread by calling pthread_create. you would pass a pointer to class or struct where at least the queue container and the mutex is a member of. that way both the main thread and the worker thread could share the container and can get exclusive access to the container:

class EventData
{
    // add members for your data and functions to access the data
    // if possible use fixed sized pod members (c types, no pointers).
};

struct ThreadData
{
     std::vector<EventData*> event_queue;
     pthread_mutex_t mux;
     bool stop;
     static void threadfunc(void *);
};



int main(....)
{
      ...
       
      ThreadData data;
      // init data 
      
      ...
      pthread_create( &thread, NULL, ThreadData::threadfunc, &data); 

      while (true)
      {
            // check for user messages
            ...
            // do idle processing
            ...
                  EventData * pEvent = NULL;
                  pthread_mutex_lock(&data.mux);
                  if (!data.event_queue.empty())
                  {
                        pEvent = data.event_queue[0];
                        data.event_queue.erase(data.event_queue.begin());
                  } 
                  pthread_mutex_unlock(&data.mux);
                  if (pEvent)
                       HandleEvent(pEvent);
                  ...

void ThreadData::threadfunc(void * parg)
{
      ThreadData * pdata  = (ThreadData *)parg;       
      while (!pdata->stop)
      {
              EventData pEvent = ReceiveEvent(...);
              if (pEvent != NULL)
              {
                    // lock the queue
                  pthread_mutex_lock(&pdata->mux);
                  pdata->event_queue.push_back(pEvent);
                  pthread_mutex_unlock(&pdata->mux);
              }
              // sleep a little amount of time
      }
}

Open in new window

Thank you very much Sarabande that definitely answers my question.