std::basic_string<> and threads

Benjamin Kosnik bkoz@rcygnus.com
Sat Apr 1 00:00:00 GMT 2000


Hmmm. This is instead of the assembly-level locking done in the v2
implementation of release? The allocator thread-safe stuff is in, as
_PTHREADS is defined if --enable-threads=posix is used to build g++.

Thus the only remaining bit is this string-specific stuff.

(And figuring out how to test it, hahah.)

>From v2's std/bastring.h (100)

#if defined __i486__ || defined __i586__ || defined __i686__
    void release ()
      {
	size_t __val;
	// This opcode exists as a .byte instead of as a mnemonic for the
	// benefit of SCO OpenServer 5.  The system assembler (which is 
	// essentially required on this target) can't assemble xaddl in 
	//COFF mode.
	asm (".byte 0xf0, 0x0f, 0xc1, 0x02" // lock; xaddl %eax, (%edx)
	    : "=a" (__val)
	    : "0" (-1), "m" (ref), "d" (&ref)
	    : "memory");

	if (__val == 1)
	  delete this;
      }
#elif defined __sparc_v9__
    void release ()
      {
	size_t __newval, __oldval = ref;
	do
	  {
	    __newval = __oldval - 1;
	    __asm__ (
#ifdef __arch64__
		     "casx	[%4], %2, %0"
#else
		     "cas	[%4], %2, %0"
#endif
		     : "=r" (__oldval), "=m" (ref)
		     : "r" (__oldval), "m" (ref), "r"(&(ref)), "0" (__newval));
	  }
	while (__newval != __oldval);

	if (__oldval == 0)
	  delete this;
      }
#else
    void release () { if (--ref == 0) delete this; }
#endif

I'm assuming that the following bits of v3's basic_string.h (175) would
have to change:

	void 
	_M_dispose(const _Alloc& __a)
	{ 
	  if (_M_state-- <= 0)  
	    _M_destroy(__a); 
	}  // XXX MT
        // bkoz strikingly similar to release....

    
	void 
	_M_destroy(const _Alloc&) throw();

	_CharT* 
	_M_refcopy() throw()
	{ 
	  ++_M_state; 
	  return _M_refdata(); 
	}  // XXX MT

(and maybe this bit from string.tcc:244, and maybe not if _M_dispose
is handled correctly.)

  template<typename _CharT, typename _Traits, typename _Alloc>
    basic_string<_CharT, _Traits, _Alloc>&
    basic_string<_CharT, _Traits, _Alloc>::assign(const basic_string& __str)
    {
      if (_M_rep() != __str._M_rep())
	{
	  // XXX MT
	  allocator_type __a = this->get_allocator();
	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
	  _M_rep()->_M_dispose(__a);
	  _M_data(__tmp);
	}
      return *this;
    }

I like the idea of not using assembly level locking. Turning off ref
counting seems a bit harsh, but then again, perhaps this should be an
option too anyway.

I'd like to see this patch (Make sure you mangle the names correctly
please). Phillip, does this seem reasonable?

Other relevant bits from past conversations about this:
http://sourceware.cygnus.com/ml/libstdc++/2000-q1/msg00116.html
http://sourceware.cygnus.com/ml/libstdc++/1999-q3/msg00167.html
http://sourceware.cygnus.com/ml/libstdc++/1999-q2/msg00339.html

-Benjamin


More information about the Libstdc++ mailing list