aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits/stl_alloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/bits/stl_alloc.h')
-rw-r--r--libstdc++-v3/include/bits/stl_alloc.h200
1 files changed, 97 insertions, 103 deletions
diff --git a/libstdc++-v3/include/bits/stl_alloc.h b/libstdc++-v3/include/bits/stl_alloc.h
index 1ae80f40512..fceed498df6 100644
--- a/libstdc++-v3/include/bits/stl_alloc.h
+++ b/libstdc++-v3/include/bits/stl_alloc.h
@@ -89,6 +89,8 @@
#include <bits/functexcept.h> // For __throw_bad_alloc
#include <bits/stl_threads.h>
+#include <bits/atomicity.h>
+
namespace std
{
/**
@@ -111,6 +113,7 @@ namespace std
{ ::operator delete(__p); }
};
+
/**
* @if maint
* A malloc-based allocator. Typically slower than the
@@ -159,7 +162,7 @@ namespace std
{
void (* __old)() = __malloc_alloc_oom_handler;
__malloc_alloc_oom_handler = __f;
- return(__old);
+ return __old;
}
};
@@ -179,11 +182,11 @@ namespace std
{
__my_malloc_handler = __malloc_alloc_oom_handler;
if (0 == __my_malloc_handler)
- std::__throw_bad_alloc();
+ std::__throw_bad_alloc();
(*__my_malloc_handler)();
__result = malloc(__n);
if (__result)
- return(__result);
+ return __result;
}
}
@@ -204,19 +207,13 @@ namespace std
(*__my_malloc_handler)();
__result = realloc(__p, __n);
if (__result)
- return(__result);
+ return __result;
}
}
#endif
-
- // Determines the underlying allocator choice for the node allocator.
-#ifdef __USE_MALLOC
- typedef __malloc_alloc_template<0> __mem_interface;
-#else
+ // Should not be referenced within the library anymore.
typedef __new_alloc __mem_interface;
-#endif
-
/**
* @if maint
@@ -230,25 +227,25 @@ namespace std
* (See @link Allocators allocators info @endlink for more.)
*/
template<typename _Tp, typename _Alloc>
- class __simple_alloc
- {
- public:
- static _Tp*
- allocate(size_t __n)
- { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
-
- static _Tp*
- allocate()
- { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
-
- static void
- deallocate(_Tp* __p, size_t __n)
- { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
-
- static void
- deallocate(_Tp* __p)
- { _Alloc::deallocate(__p, sizeof (_Tp)); }
- };
+ class __simple_alloc
+ {
+ public:
+ static _Tp*
+ allocate(size_t __n)
+ { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
+
+ static _Tp*
+ allocate()
+ { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
+
+ static void
+ deallocate(_Tp* __p, size_t __n)
+ { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
+
+ static void
+ deallocate(_Tp* __p)
+ { _Alloc::deallocate(__p, sizeof (_Tp)); }
+ };
/**
@@ -306,23 +303,16 @@ namespace std
};
-#ifdef __USE_MALLOC
-
- typedef __mem_interface __alloc;
- typedef __mem_interface __single_client_alloc;
-
-#else
-
-
/**
* @if maint
- * Default node allocator. "SGI" style. Uses __mem_interface for its
- * underlying requests (and makes as few requests as possible).
- * **** Currently __mem_interface is always __new_alloc, never __malloc*.
+ * Default node allocator. "SGI" style. Uses various allocators to
+ * fulfill underlying requests (and makes as few requests as possible
+ * when in default high-speed pool mode).
*
* Important implementation properties:
+ * 0. If globally mandated, then allocate objects from __new_alloc
* 1. If the clients request an object of size > _MAX_BYTES, the resulting
- * object will be obtained directly from the underlying __mem_interface.
+ * object will be obtained directly from __new_alloc
* 2. In all other cases, we allocate an object of size exactly
* _S_round_up(requested_size). Thus the client has enough size
* information that we can return the object to the proper free list
@@ -393,54 +383,69 @@ namespace std
} __attribute__ ((__unused__));
friend struct _Lock;
+ static _Atomic_word _S_force_new;
+
public:
// __n must be > 0
static void*
allocate(size_t __n)
{
- void* __ret = 0;
-
- if (__n > (size_t) _MAX_BYTES)
- __ret = __mem_interface::allocate(__n);
- else
- {
- _Obj* volatile* __my_free_list = _S_free_list
- + _S_freelist_index(__n);
- // Acquire the lock here with a constructor call. This
- // ensures that it is released in exit or during stack
- // unwinding.
- _Lock __lock_instance;
- _Obj* __restrict__ __result = *__my_free_list;
- if (__result == 0)
- __ret = _S_refill(_S_round_up(__n));
- else
- {
- *__my_free_list = __result -> _M_free_list_link;
- __ret = __result;
- }
- }
- return __ret;
- };
+ void* __ret = 0;
+
+ // If there is a race through here, assume answer from getenv
+ // will resolve in same direction. Inspired by techniques
+ // to efficiently support threading found in basic_string.h.
+ if (_S_force_new == 0)
+ {
+ if (getenv("GLIBCPP_FORCE_NEW"))
+ __atomic_add(&_S_force_new, 1);
+ else
+ __atomic_add(&_S_force_new, -1);
+ // Trust but verify...
+ assert (_S_force_new != 0);
+ }
+
+ if ((__n > (size_t) _MAX_BYTES) || (_S_force_new > 0))
+ __ret = __new_alloc::allocate(__n);
+ else
+ {
+ _Obj* volatile* __my_free_list = _S_free_list
+ + _S_freelist_index(__n);
+ // Acquire the lock here with a constructor call. This
+ // ensures that it is released in exit or during stack
+ // unwinding.
+ _Lock __lock_instance;
+ _Obj* __restrict__ __result = *__my_free_list;
+ if (__result == 0)
+ __ret = _S_refill(_S_round_up(__n));
+ else
+ {
+ *__my_free_list = __result -> _M_free_list_link;
+ __ret = __result;
+ }
+ }
+ return __ret;
+ }
// __p may not be 0
static void
deallocate(void* __p, size_t __n)
{
- if (__n > (size_t) _MAX_BYTES)
- __mem_interface::deallocate(__p, __n);
- else
- {
- _Obj* volatile* __my_free_list = _S_free_list
- + _S_freelist_index(__n);
- _Obj* __q = (_Obj*)__p;
-
- // Acquire the lock here with a constructor call. This
- // ensures that it is released in exit or during stack
- // unwinding.
- _Lock __lock_instance;
- __q -> _M_free_list_link = *__my_free_list;
- *__my_free_list = __q;
- }
+ if ((__n > (size_t) _MAX_BYTES) || (_S_force_new > 0))
+ __new_alloc::deallocate(__p, __n);
+ else
+ {
+ _Obj* volatile* __my_free_list = _S_free_list
+ + _S_freelist_index(__n);
+ _Obj* __q = (_Obj*)__p;
+
+ // Acquire the lock here with a constructor call. This
+ // ensures that it is released in exit or during stack
+ // unwinding.
+ _Lock __lock_instance;
+ __q -> _M_free_list_link = *__my_free_list;
+ *__my_free_list = __q;
+ }
}
#ifdef _GLIBCPP_DEPRECATED
@@ -449,6 +454,8 @@ namespace std
#endif
};
+ template<bool __threads, int __inst> _Atomic_word
+ __default_alloc_template<__threads, __inst>::_S_force_new = 0;
template<bool __threads, int __inst>
inline bool
@@ -464,8 +471,8 @@ namespace std
// We allocate memory in large chunks in order to avoid fragmenting the
- // malloc heap (or whatever __mem_interface is using) too much. We assume
- // that __size is properly aligned. We hold the allocation lock.
+ // heap too much. We assume that __size is properly aligned. We hold
+ // the allocation lock.
template<bool __threads, int __inst>
char*
__default_alloc_template<__threads, __inst>::
@@ -479,7 +486,7 @@ namespace std
{
__result = _S_start_free;
_S_start_free += __total_bytes;
- return(__result);
+ return __result ;
}
else if (__bytes_left >= __size)
{
@@ -487,7 +494,7 @@ namespace std
__total_bytes = __size * __nobjs;
__result = _S_start_free;
_S_start_free += __total_bytes;
- return(__result);
+ return __result;
}
else
{
@@ -502,7 +509,7 @@ namespace std
((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
*__my_free_list = (_Obj*)_S_start_free;
}
- _S_start_free = (char*) __mem_interface::allocate(__bytes_to_get);
+ _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get);
if (0 == _S_start_free)
{
size_t __i;
@@ -521,19 +528,19 @@ namespace std
*__my_free_list = __p -> _M_free_list_link;
_S_start_free = (char*)__p;
_S_end_free = _S_start_free + __i;
- return(_S_chunk_alloc(__size, __nobjs));
+ return _S_chunk_alloc(__size, __nobjs);
// Any leftover piece will eventually make it to the
// right free list.
}
}
_S_end_free = 0; // In case of exception.
- _S_start_free = (char*)__mem_interface::allocate(__bytes_to_get);
+ _S_start_free = (char*)__new_alloc::allocate(__bytes_to_get);
// This should either throw an exception or remedy the situation.
// Thus we assume it succeeded.
}
_S_heap_size += __bytes_to_get;
_S_end_free = _S_start_free + __bytes_to_get;
- return(_S_chunk_alloc(__size, __nobjs));
+ return _S_chunk_alloc(__size, __nobjs);
}
}
@@ -554,7 +561,7 @@ namespace std
int __i;
if (1 == __nobjs)
- return(__chunk);
+ return __chunk;
__my_free_list = _S_free_list + _S_freelist_index(__n);
// Build free list in chunk.
@@ -617,7 +624,6 @@ namespace std
typedef __default_alloc_template<true,0> __alloc;
typedef __default_alloc_template<false,0> __single_client_alloc;
-#endif /* ! __USE_MALLOC */
/**
@@ -627,10 +633,6 @@ namespace std
* of stl_alloc.h.)
*
* The underlying allocator behaves as follows.
- * - if __USE_MALLOC then
- * - thread safety depends on malloc and is entirely out of our hands
- * - __malloc_alloc_template is used for memory requests
- * - else (the default)
* - __default_alloc_template is used via two typedefs
* - "__single_client_alloc" typedef does no locking for threads
* - "__alloc" typedef is threadsafe via the locks
@@ -784,7 +786,7 @@ namespace std
};
template<typename _Alloc>
- class __allocator<void, _Alloc>
+ struct __allocator<void, _Alloc>
{
typedef size_t size_type;
typedef ptrdiff_t difference_type;
@@ -907,7 +909,6 @@ namespace std
typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
};
-#ifndef __USE_MALLOC
template<typename _Tp, bool __threads, int __inst>
struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
{
@@ -917,7 +918,6 @@ namespace std
typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> >
allocator_type;
};
-#endif
template<typename _Tp, typename _Alloc>
struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> >
@@ -940,7 +940,6 @@ namespace std
typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
};
-#ifndef __USE_MALLOC
template<typename _Tp, typename _Tp1, bool __thr, int __inst>
struct _Alloc_traits<_Tp, __allocator<_Tp1, __default_alloc_template<__thr, __inst> > >
{
@@ -950,7 +949,6 @@ namespace std
typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> >
allocator_type;
};
-#endif
template<typename _Tp, typename _Tp1, typename _Alloc>
struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > >
@@ -966,11 +964,7 @@ namespace std
// NB: This syntax is a GNU extension.
extern template class allocator<char>;
extern template class allocator<wchar_t>;
-#ifdef __USE_MALLOC
- extern template class __malloc_alloc_template<0>;
-#else
extern template class __default_alloc_template<true,0>;
-#endif
} // namespace std
#endif