Solved

blocking call

Posted on 2012-12-20
11
325 Views
Last Modified: 2013-01-21
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
0
Comment
Question by:bachra04
11 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 38713752
What kind of event are you thinking about, since you wrote "from the network"?
0
 
LVL 2

Author Comment

by:bachra04
ID: 38714953
some SIP packets coming from remote end point
0
 
LVL 2

Author Comment

by:bachra04
ID: 38716459
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.
0
 
LVL 34

Expert Comment

by:Duncan Roe
ID: 38733866
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
0
 
LVL 32

Expert Comment

by:sarabande
ID: 38739677
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
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 2

Author Comment

by:bachra04
ID: 38782925
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.
0
 
LVL 32

Accepted Solution

by:
sarabande earned 500 total points
ID: 38783693
You could use a simple std::vector<Event> as queue and protect push_back and pop_front functions by a pthread_mutex.

so, whenever an event drops in thread you lock the queue by locking the mutex and push the event to the back of the queue.

when your main thread has idle time it also locks the queue and pops an event from font of queue (index 0) - if any.

because of the mutex neither insert nor removing of event (data) would be unsafe.

Sara
0
 
LVL 2

Author Comment

by:bachra04
ID: 38797605
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
0
 
LVL 2

Author Closing Comment

by:bachra04
ID: 38799286
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
0
 
LVL 32

Expert Comment

by:sarabande
ID: 38802475
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

0
 
LVL 2

Author Comment

by:bachra04
ID: 38802564
Thank you very much Sarabande that definitely answers my question.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…

744 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now