aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/ext/rc_string_base.h
diff options
context:
space:
mode:
authorPaolo Carlini <pcarlini@suse.de>2005-11-18 11:50:22 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2005-11-18 11:50:22 +0000
commit7697e6c66a562e9bf4ef55898934079137197e2e (patch)
treea5bf3fa64144b286d112a9a48c5f870a8aa71dc0 /libstdc++-v3/include/ext/rc_string_base.h
parente0709888ef53405b609913dfe1c9bd4ff0ec750e (diff)
downloadgcc-7697e6c66a562e9bf4ef55898934079137197e2e.zip
gcc-7697e6c66a562e9bf4ef55898934079137197e2e.tar.gz
gcc-7697e6c66a562e9bf4ef55898934079137197e2e.tar.bz2
rc_string_base.h (__rc_string_base<>::_Rep): Avoid the anonymous struct extension, adjust everywhere.
2005-11-18 Paolo Carlini <pcarlini@suse.de> * include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Avoid the anonymous struct extension, adjust everywhere. * include/ext/rc_string_base.h (__rc_string_base<>::_S_empty_rep()): Just use a static member. (__rc_string_base<>::__rc_string_base(), _S_construct): Adjust. * include/ext/rc_string_base.h (__rc_string_base<>::_Rep): Use anonymous union together with _CharT to fix alignment issues, rebind to _Rep and rename _Raw_alloc to _Rep_alloc_type. (__rc_string_base<>::_Rep::_S_create, _M_destroy): Adjust consistently. * include/ext/vstring_util.h (__is_null_p): Move inside struct __vstring_utility as static _S_is_null_pointer. * include/ext/sso_string.h (__sso_string_base<>::_M_construct(std::forward_iterator_tag): Adjust. * include/ext/rc_string_base.h (__rc_string_base<>::_S_construct(std::forward_iterator_tag): Likewise. Implement Option 3 of DR 431 for ext/vstring - both available bases. * include/bits/cpp_type_traits.h (struct __is_empty): Add. * include/ext/vstring.h (__versa_string<>::swap): Delegate to this->_M_swap. * include/ext/vstring.tcc (__versa_string<>::swap): Remove. * include/ext/vstring_util.h (struct __vstring_utility<>): Add struct _Alloc_hider<>, augmented of allocator swapping facility, specialized to nop for empty allocators. * include/ext/rc_string_base.h (__rc_string_base<>::_M_swap): Use it. (__rc_string_base<>::_M_is_leaked, _M_set_sharable): Change to private. * include/ext/sso_string_base.h (__sso_string_base<>::_M_swap): Likewise. (__sso_string_base<>::_M_is_leaked, _M_set_sharable): Remove, unused. * include/ext/rc_string_base.h (__rc_string_base<>::_M_data(_CharT*): Return void. * include/ext/sso_string_base.h (__sso_string_base<>::_M_data(_CharT*): Likewise. From-SVN: r107176
Diffstat (limited to 'libstdc++-v3/include/ext/rc_string_base.h')
-rw-r--r--libstdc++-v3/include/ext/rc_string_base.h181
1 files changed, 95 insertions, 86 deletions
diff --git a/libstdc++-v3/include/ext/rc_string_base.h b/libstdc++-v3/include/ext/rc_string_base.h
index e462680..5899422 100644
--- a/libstdc++-v3/include/ext/rc_string_base.h
+++ b/libstdc++-v3/include/ext/rc_string_base.h
@@ -92,8 +92,8 @@ namespace __gnu_cxx
typedef typename _Traits::char_type value_type;
typedef _Alloc allocator_type;
- typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
- _CharT_alloc_type _CharT_alloc_type;
+ typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
+ typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
typedef typename _CharT_alloc_type::size_type size_type;
private:
@@ -107,16 +107,25 @@ namespace __gnu_cxx
// -1: leaked, one reference, no ref-copies allowed, non-const.
// 0: one reference, non-const.
// n>0: n + 1 references, operations require a lock, const.
- // 4. All fields==0 is an empty string, given the extra storage
+ // 4. All fields == 0 is an empty string, given the extra storage
// beyond-the-end for a null terminator; thus, the shared
// empty string representation needs no constructor.
struct _Rep
{
- size_type _M_length;
- size_type _M_capacity;
- _Atomic_word _M_refcount;
+ union
+ {
+ struct
+ {
+ size_type _M_length;
+ size_type _M_capacity;
+ _Atomic_word _M_refcount;
+ } _M_info;
+
+ // Only for alignment purposes.
+ _CharT _M_align;
+ };
- typedef typename _Alloc::template rebind<size_type>::other _Raw_alloc;
+ typedef typename _Alloc::template rebind<_Rep>::other _Rep_alloc_type;
_CharT*
_M_refdata() throw()
@@ -125,15 +134,15 @@ namespace __gnu_cxx
_CharT*
_M_refcopy() throw()
{
- __atomic_add(&_M_refcount, 1);
+ __atomic_add(&_M_info._M_refcount, 1);
return _M_refdata();
} // XXX MT
void
_M_set_length(size_type __n)
{
- _M_refcount = 0; // One reference.
- _M_length = __n;
+ _M_info._M_refcount = 0; // One reference.
+ _M_info._M_length = __n;
// grrr. (per 21.3.4)
// You cannot leave those LWG people alone for a second.
traits_type::assign(_M_refdata()[__n], _CharT());
@@ -150,11 +159,14 @@ namespace __gnu_cxx
_M_clone(const _Alloc&, size_type __res = 0);
};
- struct _Rep_empty : _Rep
+ struct _Rep_empty
+ : public _Rep
{
- _CharT _M_terminal;
+ _CharT _M_terminal;
};
+ static _Rep_empty _S_empty_rep;
+
// The maximum number of individual char_type elements of an
// individual string is determined by _S_max_size. This is the
// value that will be returned by max_size(). (Whereas npos
@@ -169,28 +181,12 @@ namespace __gnu_cxx
enum { _S_max_size = (((static_cast<size_type>(-1) - sizeof(_Rep))
/ sizeof(_CharT)) - 1) / 4 };
- // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
- struct _Alloc_hider : _Alloc
- {
- _Alloc_hider(_CharT* __dat, const _Alloc& __a)
- : _Alloc(__a), _M_p(__dat) { }
-
- _CharT* _M_p; // The actual data.
- };
-
// Data Member (private):
- mutable _Alloc_hider _M_dataplus;
-
- static _Rep_empty&
- _S_empty_rep()
- {
- static _Rep_empty _Empty_rep;
- return _Empty_rep;
- }
+ mutable typename _Util_Base::template _Alloc_hider<_Alloc> _M_dataplus;
- _CharT*
+ void
_M_data(_CharT* __p)
- { return (_M_dataplus._M_p = __p); }
+ { _M_dataplus._M_p = __p; }
_Rep*
_M_rep() const
@@ -206,15 +202,23 @@ namespace __gnu_cxx
void
_M_dispose(const _Alloc& __a)
{
- if (__exchange_and_add(&_M_rep()->_M_refcount, -1) <= 0)
+ if (__exchange_and_add(&_M_rep()->_M_info._M_refcount, -1) <= 0)
_M_rep()->_M_destroy(__a);
} // XXX MT
+ bool
+ _M_is_leaked() const
+ { return _M_rep()->_M_info._M_refcount < 0; }
+
+ void
+ _M_set_sharable()
+ { _M_rep()->_M_info._M_refcount = 0; }
+
void
_M_leak_hard();
// _S_construct_aux is used to implement the 21.3.1 para 15 which
- // requires special behaviour if _InIter is an integral type
+ // requires special behaviour if _InIterator is an integral type
template<class _InIterator>
static _CharT*
_S_construct_aux(_InIterator __beg, _InIterator __end,
@@ -266,31 +270,19 @@ namespace __gnu_cxx
size_type
_M_length() const
- { return _M_rep()->_M_length; }
+ { return _M_rep()->_M_info._M_length; }
size_type
_M_capacity() const
- { return _M_rep()->_M_capacity; }
+ { return _M_rep()->_M_info._M_capacity; }
bool
_M_is_shared() const
- { return _M_rep()->_M_refcount > 0; }
-
- bool
- _M_is_leaked() const
- { return _M_rep()->_M_refcount < 0; }
-
- void
- _M_set_sharable()
- { _M_rep()->_M_refcount = 0; }
+ { return _M_rep()->_M_info._M_refcount > 0; }
void
_M_set_leaked()
- { _M_rep()->_M_refcount = -1; }
-
- void
- _M_set_length(size_type __n)
- { _M_rep()->_M_set_length(__n); }
+ { _M_rep()->_M_info._M_refcount = -1; }
void
_M_leak() // for use in begin() & non-const op[]
@@ -299,8 +291,12 @@ namespace __gnu_cxx
_M_leak_hard();
}
+ void
+ _M_set_length(size_type __n)
+ { _M_rep()->_M_set_length(__n); }
+
__rc_string_base()
- : _M_dataplus(_S_empty_rep()._M_refcopy(), _Alloc()) { }
+ : _M_dataplus(_Alloc(), _S_empty_rep._M_refcopy()) { }
__rc_string_base(const _Alloc& __a);
@@ -310,7 +306,7 @@ namespace __gnu_cxx
template<typename _InputIterator>
__rc_string_base(_InputIterator __beg, _InputIterator __end,
- const _Alloc& __a);
+ const _Alloc& __a);
~__rc_string_base()
{ _M_dispose(_M_get_allocator()); }
@@ -320,12 +316,7 @@ namespace __gnu_cxx
{ return _M_dataplus; }
void
- _M_swap(__rc_string_base& __rcs)
- {
- _CharT* __tmp = _M_data();
- _M_data(__rcs._M_data());
- __rcs._M_data(__tmp);
- }
+ _M_swap(__rc_string_base& __rcs);
void
_M_assign(const __rc_string_base& __rcs);
@@ -338,6 +329,10 @@ namespace __gnu_cxx
};
template<typename _CharT, typename _Traits, typename _Alloc>
+ typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep_empty
+ __rc_string_base<_CharT, _Traits, _Alloc>::_S_empty_rep;
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep*
__rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
_S_create(size_type __capacity, size_type __old_capacity,
@@ -388,8 +383,8 @@ namespace __gnu_cxx
// plus sizeof(size_type) - 1 to upper round to a size multiple
// of sizeof(size_type).
// Whew. Seemingly so needy, yet so elemental.
- size_type __size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
- + sizeof(size_type) - 1);
+ size_type __size = ((__capacity + 1) * sizeof(_CharT)
+ + 2 * sizeof(_Rep) - 1);
const size_type __adj_size = __size + __malloc_header_size;
if (__adj_size > __pagesize && __capacity > __old_capacity)
@@ -399,16 +394,14 @@ namespace __gnu_cxx
// Never allocate a string bigger than _S_max_size.
if (__capacity > size_type(_S_max_size))
__capacity = size_type(_S_max_size);
- __size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
- + sizeof(size_type) - 1);
+ __size = (__capacity + 1) * sizeof(_CharT) + 2 * sizeof(_Rep) - 1;
}
// NB: Might throw, but no worries about a leak, mate: _Rep()
// does not throw.
- void* __place = _Raw_alloc(__alloc).allocate(__size
- / sizeof(size_type));
- _Rep *__p = new (__place) _Rep;
- __p->_M_capacity = __capacity;
+ _Rep* __place = _Rep_alloc_type(__alloc).allocate(__size / sizeof(_Rep));
+ _Rep* __p = new (__place) _Rep;
+ __p->_M_info._M_capacity = __capacity;
return __p;
}
@@ -417,10 +410,9 @@ namespace __gnu_cxx
__rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
_M_destroy(const _Alloc& __a) throw ()
{
- const size_type __size = ((_M_capacity + 1) * sizeof(_CharT)
- + sizeof(_Rep) + sizeof(size_type) - 1);
- _Raw_alloc(__a).deallocate(reinterpret_cast<size_type*>(this),
- __size / sizeof(size_type));
+ const size_type __size = ((_M_info._M_capacity + 1) * sizeof(_CharT)
+ + 2 * sizeof(_Rep) - 1);
+ _Rep_alloc_type(__a).deallocate(this, __size / sizeof(_Rep));
}
template<typename _CharT, typename _Traits, typename _Alloc>
@@ -429,41 +421,40 @@ namespace __gnu_cxx
_M_clone(const _Alloc& __alloc, size_type __res)
{
// Requested capacity of the clone.
- const size_type __requested_cap = _M_length + __res;
- _Rep* __r = _Rep::_S_create(__requested_cap, _M_capacity, __alloc);
+ const size_type __requested_cap = _M_info._M_length + __res;
+ _Rep* __r = _Rep::_S_create(__requested_cap, _M_info._M_capacity,
+ __alloc);
- if (_M_length)
- _S_copy(__r->_M_refdata(), _M_refdata(), _M_length);
+ if (_M_info._M_length)
+ _S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
- __r->_M_set_length(_M_length);
+ __r->_M_set_length(_M_info._M_length);
return __r->_M_refdata();
}
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(const _Alloc& __a)
- : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) { }
+ : _M_dataplus(__a, _S_construct(size_type(), _CharT(), __a)) { }
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(const __rc_string_base& __rcs)
- : _M_dataplus(__rcs._M_grab(_Alloc(__rcs._M_get_allocator()),
- __rcs._M_get_allocator()),
- __rcs._M_get_allocator()) { }
+ : _M_dataplus(__rcs._M_get_allocator(),
+ __rcs._M_grab(_Alloc(__rcs._M_get_allocator()),
+ __rcs._M_get_allocator())) { }
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(size_type __n, _CharT __c, const _Alloc& __a)
- : _M_dataplus(_S_construct(__n, __c, __a), __a)
- { }
+ : _M_dataplus(__a, _S_construct(__n, __c, __a)) { }
template<typename _CharT, typename _Traits, typename _Alloc>
template<typename _InputIterator>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a)
- : _M_dataplus(_S_construct(__beg, __end, __a), __a)
- { }
+ : _M_dataplus(__a, _S_construct(__beg, __end, __a)) { }
template<typename _CharT, typename _Traits, typename _Alloc>
void
@@ -487,7 +478,7 @@ namespace __gnu_cxx
std::input_iterator_tag)
{
if (__beg == __end && __a == _Alloc())
- return _S_empty_rep()._M_refcopy();
+ return _S_empty_rep._M_refcopy();
// Avoid reallocation for common case.
_CharT __buf[128];
@@ -532,10 +523,10 @@ namespace __gnu_cxx
std::forward_iterator_tag)
{
if (__beg == __end && __a == _Alloc())
- return _S_empty_rep()._M_refcopy();
+ return _S_empty_rep._M_refcopy();
// NB: Not required, but considered best practice.
- if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
+ if (__builtin_expect(_S_is_null_pointer(__beg) && __beg != __end, 0))
std::__throw_logic_error(__N("__rc_string_base::"
"_S_construct NULL not valid"));
@@ -560,7 +551,7 @@ namespace __gnu_cxx
_S_construct(size_type __n, _CharT __c, const _Alloc& __a)
{
if (__n == 0 && __a == _Alloc())
- return _S_empty_rep()._M_refcopy();
+ return _S_empty_rep._M_refcopy();
// Check for out_of_range and length_error exceptions.
_Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
@@ -574,6 +565,24 @@ namespace __gnu_cxx
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::
+ _M_swap(__rc_string_base& __rcs)
+ {
+ if (_M_is_leaked())
+ _M_set_sharable();
+ if (__rcs._M_is_leaked())
+ __rcs._M_set_sharable();
+
+ _CharT* __tmp = _M_data();
+ _M_data(__rcs._M_data());
+ __rcs._M_data(__tmp);
+
+ // NB: Implement Option 3 of DR 431 (see N1599).
+ _M_dataplus._M_alloc_swap(__rcs._M_dataplus);
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ __rc_string_base<_CharT, _Traits, _Alloc>::
_M_assign(const __rc_string_base& __rcs)
{
if (_M_rep() != __rcs._M_rep())