On Fri, 2010-01-08 at 10:36 -0500, Dale Worley wrote:
> On Thu, 2010-01-07 at 16:46 -0500, Scott Lawrence wrote:
> > On Thu, 2010-01-07 at 15:50 -0500, Dale Worley wrote:
> > > More exactly, the problem is that whether and where the lock is held is
> > > not determined by the static structure of the code.  That is what OsLock
> > > was designed to allow, and OsLock::release() violates that.  Within that
> > > context, I can replace ::release with OsUnLock with only a slight loss
> > > of efficiency, and have the lock structure be statically determined.
> > > With that structure, gotchas are still possible, but much less so than
> > > with manual locking.
> > 
> > Sorry - I'm not clear on what change that implies... could you put in a
> > code snippet like the one you started with to illustrate?
> 
> Here's an example (with some extraneous code deleted):
> 
> OsStatus SipSubscribeClient::handleRestartEvent(const UtlString& handle)
> {
>    OsLock lock(mSemaphore);
> 
>    // Get the SubscriptionGroupState.
>    // Due to race conditions, it may no longer exist.
>    SubscriptionGroupState* groupState = getGroupStateByOriginalHandle(handle);
>    if (groupState)
>    {
>       // Test whether restart is set.
>       // It may be false because the subscription group is being ended.
>       if (groupState->mRestart)
>       {
>          groupState->setRestartTimer();
> 
>          OsUnLock unlock(lock);
>          groupState = NULL;   // Remember that groupState is no longer 
> reliable,
>                               // because it points to a structure protected by
>                               // mSemaphore.
>          
>          reestablish(handle);
>       }
>    }
> }
> 
> The problem to be solved is that reestablish() needs to be called with
> mSemaphore unlocked.  OsUnLock causes mSemaphore to be released within
> its scope.

I see no advantage at all in the above over using the existing acquire
and release interfaces on the underlying semaphores, and a (to my mind)
considerable disadvantage - that the scope of the OsLock is no longer
exactly the scope of the object. 

My perception of the value of the OsLock object wrapper is two-fold: it
is easy to use for the simple cases (you don't need to worry about
forgetting to add the release call because the scope will do it), but
also that it makes a nice programmer friendly semantic association
between the block scope and the lock scope.  When I do:

{
    ... code-a ...
    {
         OsLock critical(mutex);

         ... code-b ...
    }
    ... code-c ...
}

the inner set of {} become a nice syntactic part of the lock.  I know
unambiguously that regardless of how complex it becomes, code-b is all
in the critical region and protected, and neither code-a nor code-c can
be.  What you're suggesting preserves the latter, but not the former.

On the other hand, if I see this code:

{
    ... code-a ...
    
    mutex.acquire();

    ... code-b ...

    mutex.release();

    ... code-c ...
}

(whether or not there are inner braces), then I know that I have to be
careful everywhere in code-b to keep track of the lock state, because
there could be a release() in there somewhere?


_______________________________________________
sipx-dev mailing list [email protected]
List Archive: http://list.sipfoundry.org/archive/sipx-dev
Unsubscribe: http://list.sipfoundry.org/mailman/listinfo/sipx-dev
sipXecs IP PBX -- http://www.sipfoundry.org/

Reply via email to