Thread overview
Minimize lock time
Jun 10, 2010
Kagamin
Jun 10, 2010
Kagamin
Jun 10, 2010
Simen kjaeraas
June 10, 2010
Let's consider the following code:

synchronized(syncRoot)
{
  if(condition)opSuccess();
  else writeln(possibly,slow);
}

Suppose the else close doesn't need to be executed in lock domain and can be slow. How to minimize lock time here?

synchronized(syncRoot)
{
  if(condition)opSuccess();
  else goto Lwrite;
}
Lwrite: writeln(possibly,slow);

We can do this... but...
June 10, 2010
On Thu, 10 Jun 2010 02:54:37 -0400, Kagamin <spam@here.lot> wrote:
> 
> Let's consider the following code:
> 
> synchronized(syncRoot)
> {
>   if(condition)opSuccess();
>   else writeln(possibly,slow);
> }
> 
> Suppose the else close doesn't need to be executed in lock domain and can be slow. How to minimize lock time here?
> 
> synchronized(syncRoot)
> {
>   if(condition)opSuccess();
>   else goto Lwrite;
> }
> Lwrite: writeln(possibly,slow);
> 
> We can do this... but...

A common pattern is to use a boolean flag:

bool success;
synchronized (syncRoot)
{
  success = (condition);
}

if (success) opSuccess();
else writeln(possibly, slow);
June 10, 2010
Justin Spahr-Summers Wrote:

> On Thu, 10 Jun 2010 02:54:37 -0400, Kagamin <spam@here.lot> wrote:
> > 
> > Let's consider the following code:
> > 
> > synchronized(syncRoot)
> > {
> >   if(condition)opSuccess();
> >   else writeln(possibly,slow);
> > }
> > 
> > Suppose the else close doesn't need to be executed in lock domain and can be slow. How to minimize lock time here?
> > 
> > synchronized(syncRoot)
> > {
> >   if(condition)opSuccess();
> >   else goto Lwrite;
> > }
> > Lwrite: writeln(possibly,slow);
> > 
> > We can do this... but...
> 
> A common pattern is to use a boolean flag:
> 
> bool success;
> synchronized (syncRoot)
> {
>   success = (condition);
> }
> 
> if (success) opSuccess();
> else writeln(possibly, slow);

1. opSuccess must be called in lock.
2. this solution doesn't scale: there can be three or more such transitions.
June 10, 2010
Kagamin <spam@here.lot> wrote:

> Let's consider the following code:
>
> synchronized(syncRoot)
> {
>   if(condition)opSuccess();
>   else writeln(possibly,slow);
> }
>
> Suppose the else close doesn't need to be executed in lock domain and can be slow. How to minimize lock time here?
>
> synchronized(syncRoot)
> {
>   if(condition)opSuccess();
>   else goto Lwrite;
> }
> Lwrite: writeln(possibly,slow);
>
> We can do this... but...

A flag, as has been mentioned, would work.

Other solutions that might work:

////////
synchronized(syncRoot)
{
  if (condition)
  {
    opSuccess();
    return;
  }
}
writeln(possibly,slow);

////////
do
{
  synchronized(syncRoot)
  {
    if (condition)
    {
      opSuccess();
      break;
    }
  }
  writeln(possibly, slow);
} while (false);

////////
bool helperFunc( ) {
  synchronized( syncRoot )
  {
    if ( condition ) {
      opSuccess();
      return true;
    } else {
      return false;
    }
  }
}

if (!helperFunc( )) {
   writeln( possibly, slow );
}

--
Simen
June 11, 2010
On Thu, 10 Jun 2010 12:42:09 +0200, Simen kjaeraas <simen.kjaras@gmail.com> wrote:
> 
> Kagamin <spam@here.lot> wrote:
> 
> > Let's consider the following code:
> >
> > synchronized(syncRoot)
> > {
> >   if(condition)opSuccess();
> >   else writeln(possibly,slow);
> > }
> >
> > Suppose the else close doesn't need to be executed in lock domain and can be slow. How to minimize lock time here?
> >
> > synchronized(syncRoot)
> > {
> >   if(condition)opSuccess();
> >   else goto Lwrite;
> > }
> > Lwrite: writeln(possibly,slow);
> >
> > We can do this... but...
> 
> A flag, as has been mentioned, would work.
> 
> Other solutions that might work:
> 
> ////////
> synchronized(syncRoot)
> {
>    if (condition)
>    {
>      opSuccess();
>      return;
>    }
> }
> writeln(possibly,slow);
> 
> ////////
> do
> {
>    synchronized(syncRoot)
>    {
>      if (condition)
>      {
>        opSuccess();
>        break;
>      }
>    }
>    writeln(possibly, slow);

All good suggestions. synchronized(), in general, just doesn't scale very well (though no fault of D's). If you're doing very complex things, you might have better luck with a semaphore of some kind. As always, though, avoiding the need for synchronization is best.
June 14, 2010
On Thu, 10 Jun 2010 02:54:37 -0400, Kagamin <spam@here.lot> wrote:

> Let's consider the following code:
>
> synchronized(syncRoot)
> {
>   if(condition)opSuccess();
>   else writeln(possibly,slow);
> }
>
> Suppose the else close doesn't need to be executed in lock domain and can be slow. How to minimize lock time here?
>
> synchronized(syncRoot)
> {
>   if(condition)opSuccess();
>   else goto Lwrite;
> }
> Lwrite: writeln(possibly,slow);
>
> We can do this... but...

What about using a Mutex object?

mut.lock();
if(condition)
{
   scope(exit) mut.unlock();
   opSuccess();
}
else
{
   mut.unlock();
   writeln(possibly, slow);
}

I think it's in core.sync or something like that.  Mutex can even take over the standard monitor element of another object, so for instance you could assign it as the monitor of your syncRoot, so your other code that uses syncRoot and synchronized still works.

-Steve