Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Welcome Guest | Log In | Register | Benefits
Channels ▼
RSS

Optimizations That Aren't (In a Multithreaded World)


June 1999/Optimizations That Aren't (In a Multithreaded World)/Figure 1

Figure 1: Various thread-safe and thread-unsafe implementations of COW

// Thread-unsafe COW: no locks
//
void String::EnsureUnique() {
   if( data_->refs > 1 ) {
      StringBuf* newdata = new StringBuf( *data_ );
      --data_->refs;   // now all the real work is
      data_ = newdata; //  done, so take ownership
   }
}
// Thread-safe COW: atomic integer operations
//
// Uses atomic integer calls to serialize access to data_->refs. 
// Note that the IntAtomic* calls are not necessary function 
// calls, but can be as efficient as a native assembler 
// instruction. They still introduce overhead, however, because
// EnsureUnique must be called by every possibly-mutating String 
// function, and the IntAtomic* operations are slower than normal 
// integer operations.
//
void String::EnsureUnique() {
   if( IntAtomicCompare( data_->refs, 1 ) > 0 ) {
      StringBuf* newdata = new StringBuf( *data_ );
      if( IntAtomicDecrement( data_->refs ) < 1 ) {
         delete newdata;  // just in case two threads
         data_->refs = 1; //  are trying this at once
      }
      else {              // now all the real work is
         data_ = newdata; //  done, so take ownership
      }
   }
}
// Thread-safe COW: critical sections
//
// Each data_ buffer contains a critical section object for 
// serializing access to data_->refs. This method is needlessly 
// inefficient, but it is used in some popular commercial string 
// libraries. EnsureUnique still is called by every possibly-
// mutating String function, but the overhead is worse than with 
// IntAtomic* functions.
//
void String::EnsureUnique() {
   Lock<CriticalSection> l(data_->cs); //---------
   if( data_->refs > 1 ) {
      StringBuf* newdata = new StringBuf( *data_ );
      --data_->refs;
      data_ = newdata;
   }
   l.Unlock(); //---------------------------------
}



Related Reading


More Insights