< Previous by Date Date Index Next by Date >
< Previous in Thread Thread Index  

Re: [reSIProcate-users] clientSubscription NOTIFY problem


...inline...

On Mon, Jun 28, 2010 at 7:55 AM, Klaus Darilion <klaus.mailinglists@xxxxxxxxx> wrote:
Hi Scott!

Thanks for you answer.

In my code the API calls (application thread) are not done from the same thread as the ->process call (dumThread):

  SelectInterruptor mSelectInterruptor;
  SipStack stack(0, DnsStub::EmptyNameserverList, &mSelectInterruptor);
  DialogUsageManager clientDum(stack);

  InterruptableStackThread stackThread(stack, mSelectInterruptor);
  stackThread.run();
  DumThread dumThread(clientDum);
  dumThread.run();

  clientDum.addTransport(UDP, 10000 + rand()&0x7fff, V4);
  clientDum.setClientRegistrationHandler(&clientHandler);
  ...setting master profile ....


  SharedPtr<SipMessage> regMessage =
       clientDum.makeRegistration(userAor);
  clientDum.send( regMessage );

Does this mean that above code is broken as it is not thread safe?

Correct.
 
If I understand it correctly, a workaround would be to use ->post as described here: http://www.resiprocate.org/DUM_Threading#Queueing_DUM_Commands_Solution

But this looks very cumbersome to write a wrapper class for every DUM API method call.

Yes it can be cumbersome.  There are already a number of the InviteSession API's with built-in post calls that are thread safe.  See the API calls ending in Comand (ie. provideOfferCommand).
 
I also read about using a DUM FIFO but I could not find any implemenation details/sample code for that. Is there some sample code?

This is the same as the post mechanism - messages are posted to the DUM FIFO.
 
Maybe it is best for to just implement my own DumThread which protects the dum->process() call with a Mutex.

That is certainly the easiest approach.
 
Therefore, I tried to analyze how DumThread works and how it calls dum->process, but surprisingly it does not all - it uses a fifo and internalProcess():

        std::auto_ptr<Message> msg(mDum.mFifo.getNext(1000));
        if (msg.get())
        {
           mDum.internalProcess(msg);
        }


I wonder if there is any advantage in using above construct. I would have implemented it in the following way.

while (!isShutdown())
 Sleep(10); // 10 ms
 myMutex.Lock();
 while(clientDum.process());
 myMutex.Unlock();
}

Your implementation will wake up every 10ms - lock the mutex and call process.  The DumThread implementation will block waiting for an event on the FIFO - it is more efficient.  Also - take a look at the following API on DialogUsageManager:  bool process(int timeoutMs, Lockable* mutex = NULL);   // Specify -1 for infinte timeout.   You can pass a resip::Mutex as the Lockable and will make sure it only locks if there are messages on the FIFO to be processed.  I would implement a LockableDumThread class with a run loop like:

   while (!isShutdown())
   {
      try
      {
         while(mDum.process(1000, &lock));
      }
      catch (BaseException& e)
      {
         WarningLog (<< "Unhandled exception: " << e);
      }
   }  
 
And then in the application thread also using myMutex to avoid concurrent DUM access. Would that be safe?

Yes.
 
thanks
Klaus

Am 25.06.2010 20:26, schrieb Scott Godin:
... inline...

On Fri, Jun 25, 2010 at 2:19 PM, Klaus Darilion
<klaus.mailinglists@xxxxxxxxx <mailto:klaus.mailinglists@xxxxxxxxx>> wrote:

   Hi Scott!

   I just modified the basicRegister example to start a DumThread and a
   InterruptableStackThread. I have removed all stack.process(fdset)
   and clientDum.process() calls and it still works fine.

    From the application, I still call DUM methods, e.g.

      SharedPtr<SipMessage> regMessage =
   clientDum.makeRegistration(userAor);
      clientDum.send( regMessage );

   just as before.

   The Wiki mentions that the application may need to provide its own
   mutex to protect access to DUM. Is this only needed when the
   application itself is multithreaded or also if the application is
   just single threaded?


You cannot call any DUM API's from a thread that is different from the
thread calling process.  So in your case (using DumThread) you still
need to protect calls to DUM.

   For example, although the application is single threaded, what
   happens if DUM calls my ClientRegistrationHandler and I call some
   DUM methods from within the Handler (which might happen at the same
   time the application calls some DUM methods)?


The callbacks themselves are running in the DumThread, so it is safe to
call other DUM methods from the callbacks, since they will be called in
the single DumThread.  However, you cannot call the DUM methods outside
of these callbacks without protecting them, or queueing commands to the
DUM FIFO.

Scott


   Thanks
   Klaus

   Am 09.06.2010 18:00, schrieb Scott Godin:

       There is no "out-of-box" threading class that will handle both
       the stack
       and dum - but it shouldn't be hard to create on if you like.
         Otherwise,
       you will need both DumThread and InterruptableStackThread.

       Scott

       On Wed, Jun 9, 2010 at 11:54 AM, Klaus Darilion
       <klaus.mailinglists@xxxxxxxxx
       <mailto:klaus.mailinglists@xxxxxxxxx>
       <mailto:klaus.mailinglists@xxxxxxxxx
       <mailto:klaus.mailinglists@xxxxxxxxx>>> wrote:

           Hi Scott!


           Am 08.06.2010 19:32, schrieb Scott Godin:

                   Further, is there a mode to let stack/dum create a
       thread
               itself for

                   internal processing (so that I do not need an event
       loop in the
                   application, but wait for callback events)?


               There is a pretty detailed wiki page on all this stuff:
       http://www.resiprocate.org/DUM_Threading


           Not sure if I got it right: I do not care about if dum and
       stack use
           the same thread or a different one  - I just want that all
       the SIP
           stuff is happening asynchronously independent from the
       application's
           thread.

           Will using DumThread solve my issues or do I have to use
       StackThread
           (or InterruptableStackThread) too?

           Thanks
           Klaus