vcl_alloc.h
来自「DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.」· C头文件 代码 · 共 805 行 · 第 1/2 页
H
805 行
/*
* Copyright (c) 1996-1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* Copyright (c) 1997
* Moscow Center for SPARC Technology
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Moscow Center for SPARC Technology makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/
#ifndef vcl_emulation_alloc_h
#define vcl_emulation_alloc_h
//:
// \file
// \brief This implements some standard node allocators
//
// These are \b NOT the same as the allocators in the C++ draft standard or in
// in the original STL. They do not encapsulate different pointer
// types; indeed we assume that there is only one pointer type.
// The allocation primitives are intended to allocate individual objects,
// not larger arenas as with the original STL allocators.
//
// \verbatim
// Modifications
// 180598 AWF Indented ifdefs properly. Very important task that.
// \endverbatim
#include "vcl_stlconf.h"
#ifndef __ALLOC
# define __ALLOC vcl_alloc
#endif
//#include <vcl_cstdlib.h>
#include <vcl_cstddef.h>
#include <vcl_cstring.h>
#include <vcl_cassert.h>
#ifndef __RESTRICT
# define __RESTRICT
#endif
#if !defined(_PTHREADS) && !defined(_NOTHREADS) \
&& !defined(__STL_SGI_THREADS) && !defined(__STL_WIN32THREADS)
# define _NOTHREADS
#endif
#include "vcl_bool.h"
#if !defined ( __STL_NO_EXCEPTIONS )
# if defined (__STL_BAD_ALLOC_DEFINED)
# include <vcl_new.h>
# else
struct bad_alloc {};
# endif
# define __THROW_BAD_ALLOC throw bad_alloc()
#elif !defined(__THROW_BAD_ALLOC)
extern void vcl_alloc_throw_bad_alloc(char const *, int);
# define __THROW_BAD_ALLOC vcl_alloc_throw_bad_alloc(__FILE__, __LINE__)
#endif
# if defined ( __STL_USE_ABBREVS )
// ugliness is intentional - to reduce conflicts probability
# define __malloc_alloc vcl_MA
# define __alloc vcl_DA
# endif
//: Allocator adaptor to check size arguments for debugging.
// Reports errors using assert. Checking can be disabled with
// NDEBUG, but it's far better to just use the underlying allocator
// instead when no checking is desired.
// There is some evidence that this can confuse Purify.
template <class Alloc>
class debug_alloc
{
public:
typedef Alloc allocator_type;
typedef typename Alloc::value_type value_type; //awf for SGI
private:
#if !__STL_EAGER_TYPECHECK
enum {
type_size=sizeof(Alloc::value_type), // awf
safe_size=(type_size>0 ? type_size :1),
extra_chunk=8/safe_size+(int)(8%safe_size>0),
extra = 8
};
#else
#define type_size (sizeof(Alloc::value_type))
#define safe_size (type_size()>0 ? type_size() :1)
#define extra_chunk (8/safe_size+(int)(8%safe_size>0))
#define extra 8
#endif
// Size of space used to store size. Note that this must be
// large enough to preserve alignment.
public:
static void * allocate(vcl_size_t n)
{
char *result = (char *)allocator_type::allocate(n + extra_chunk);
*(vcl_size_t *)result = n;
return result + extra;
}
static void deallocate(void *p, vcl_size_t n)
{
char * real_p = (char *)p - extra;
assert(*(vcl_size_t *)real_p == n);
allocator_type::deallocate(real_p, n + extra);
}
static void *
reallocate(void *p, vcl_size_t old_sz, vcl_size_t new_sz)
{
char * real_p = (char *)p - extra;
assert(*(vcl_size_t *)real_p == old_sz);
char * result = (char *)
allocator_type::reallocate(real_p, old_sz + extra_chunk, new_sz + extra_chunk);
*(vcl_size_t *)result = new_sz;
return result + extra;
}
#undef type_size
#undef safe_size
#undef extra_chunk
#undef extra
};
// That is an adaptor for working with any alloc provided below
template<class T, class Alloc>
class vcl_simple_alloc
{
typedef Alloc alloc_type;
public:
typedef typename Alloc::value_type alloc_value_type; // awf
typedef T value_type;
#if !__STL_EAGER_TYPECHECK
enum {
chunk = sizeof(value_type)/sizeof(alloc_value_type)+(sizeof(value_type)%sizeof(alloc_value_type)>0)
};
#else
// note: any out-of-line template definitions will not see this.
#define chunk (sizeof(value_type)/sizeof(alloc_value_type)+(sizeof(value_type)%sizeof(alloc_value_type)>0))
#endif
static value_type *allocate(vcl_size_t n) { return 0 == n? 0 : (value_type*) alloc_type::allocate(n * chunk); }
static value_type *allocate(void) { return (value_type*) alloc_type::allocate(chunk); }
static void deallocate(value_type *p, vcl_size_t n) { if (0 != n) alloc_type::deallocate(p, n * chunk); }
static void deallocate(value_type *p) { alloc_type::deallocate(p, chunk); }
#undef chunk
};
// New-based allocator. Typically slower than default alloc below.
// Typically thread-safe and more storage efficient.
template <int inst>
class __new_alloc
{
public:
// this one is needed for proper vcl_simple_alloc wrapping
typedef char value_type;
static void* allocate(vcl_size_t n) { return 0 == n ? 0 : ::operator new(n);}
static void* reallocate(void *p, vcl_size_t old_sz, vcl_size_t new_sz)
{
void* result = allocate(new_sz);
vcl_size_t copy_sz = new_sz > old_sz? old_sz : new_sz;
vcl_memcpy(result, p, copy_sz);
deallocate(p, old_sz);
return result;
}
static void deallocate(void* p) { ::operator delete(p); }
static void deallocate(void* p, vcl_size_t) { ::operator delete(p); }
};
typedef __new_alloc<0> new_alloc;
// Malloc-based allocator. Typically slower than default alloc below.
// Typically thread-safe and more storage efficient.
typedef void (* __oom_handler_type)();
template <int inst>
class __malloc_alloc
{
private:
static void *oom_malloc(vcl_size_t);
static void *oom_realloc(void *, vcl_size_t);
static __oom_handler_type oom_handler;
public:
// this one is needed for proper vcl_simple_alloc wrapping
typedef char value_type;
static void * allocate(vcl_size_t n)
{
void *result = malloc(n);
if (0 == result) result = oom_malloc(n);
return result;
}
static void deallocate(void *p, vcl_size_t /* n */) { free(p); }
static void * reallocate(void *p, vcl_size_t /* old_sz */, vcl_size_t new_sz)
{
void * result = realloc(p, new_sz);
if (0 == result) result = oom_realloc(p, new_sz);
return result;
}
static __oom_handler_type set_malloc_handler(__oom_handler_type f)
{
__oom_handler_type old = oom_handler;
oom_handler = f;
return old;
}
};
// malloc_alloc out-of-memory handling
# if ( __STL_STATIC_TEMPLATE_DATA > 0 )
template <int inst>
__oom_handler_type __malloc_alloc<inst>::oom_handler=(__oom_handler_type)0;
# else
__DECLARE_INSTANCE(__oom_handler_type, __malloc_alloc<0>::oom_handler,0);
# endif /* ( __STL_STATIC_TEMPLATE_DATA > 0 ) */
template <int inst>
void * __malloc_alloc<inst>::oom_malloc(vcl_size_t n)
{
__oom_handler_type my_malloc_handler;
void *result = 0;
while (!result) {
my_malloc_handler = oom_handler;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();
result = malloc(n);
}
return result;
}
template <int inst>
void * __malloc_alloc<inst>::oom_realloc(void *p, vcl_size_t n)
{
__oom_handler_type my_malloc_handler;
void *result = 0;
while (!result) {
my_malloc_handler = oom_handler;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();
result = realloc(p, n);
}
return result;
}
typedef __malloc_alloc<0> vcl_malloc_alloc;
# if defined ( __STL_USE_NEWALLOC )
# if defined ( __STL_DEBUG_ALLOC )
typedef debug_alloc<new_alloc> vcl_alloc;
# else
typedef new_alloc vcl_alloc;
# endif
typedef new_alloc single_client_alloc;
typedef new_alloc multithreaded_alloc;
# else /* ! __STL_USE_NEWALLOC */
# ifdef __STL_USE_MALLOC
# if defined ( __STL_DEBUG_ALLOC )
typedef debug_alloc<vcl_malloc_alloc> vcl_alloc;
# else
typedef vcl_malloc_alloc vcl_alloc;
# endif
typedef vcl_malloc_alloc single_client_alloc;
typedef vcl_malloc_alloc multithreaded_alloc;
# else /* ! __STL_USE_MALLOC */
// global-level stuff
// fbp : put all this stuff here
# ifdef _NOTHREADS
// Thread-unsafe
# define __NODE_ALLOCATOR_LOCK
# define __NODE_ALLOCATOR_UNLOCK
# define __NODE_ALLOCATOR_THREADS false
# define __VOLATILE
# else /* ! _NOTHREADS */
# ifdef _PTHREADS
// POSIX Threads
// This is dubious, since this is likely to be a high contention
// lock. The Posix standard appears to require an implemention
// that makes convoy effects likely. Performance may not be
// adequate.
# include <pthread.h>
// pthread_mutex_t __node_allocator_lock = PTHREAD_MUTEX_INITIALIZER;
# define __NODE_ALLOCATOR_LOCK \
if (threads) pthread_mutex_lock(&__node_allocator_lock)
# define __NODE_ALLOCATOR_UNLOCK \
if (threads) pthread_mutex_unlock(&__node_allocator_lock)
# define __NODE_ALLOCATOR_THREADS true
# define __VOLATILE volatile // Needed at -O3 on SGI
# endif /* _PTHREADS */
# ifdef __STL_WIN32THREADS
# if !defined (__STL_WINDOWS_H_INCLUDED)
# define NOMINMAX
//# include <windows.h>
# undef min
# undef max
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
// include windows.h outside #if !defined (__STL_WINDOWS_H_INCLUDED)
// because including windows.h can cause the #if/#endif nesting
// to exceed the maximum supported by Visual C++ (and windows.h
// has an #ifndef _WINDOWS_ / #endif guard)
# include <windows.h>
// CRITICAL_SECTION __node_allocator_lock;
// bool __node_allocator_lock_initialized;
// this one is needed to ensure correct initialization order
// and to avoid excess instances
struct __stl_critical_section_wrapper {
CRITICAL_SECTION section;
__stl_critical_section_wrapper() {
InitializeCriticalSection(§ion);
}
};
# define __NODE_ALLOCATOR_LOCK \
EnterCriticalSection(&__node_allocator_lock.section)
# define __NODE_ALLOCATOR_UNLOCK \
LeaveCriticalSection(&__node_allocator_lock.section)
# define __NODE_ALLOCATOR_THREADS true
# define __VOLATILE volatile // may not be needed
# endif /* __STL_WIN32THREADS */
# ifdef __STL_SGI_THREADS
// This should work without threads, with sproc threads, or with
// pthreads. It is suboptimal in all cases.
// It is unlikely to even compile on nonSGI machines.
# include <malloc.h>
# define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) \
{ __lock(&__node_allocator_lock); }
# define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) \
{ __unlock(&__node_allocator_lock); }
# define __NODE_ALLOCATOR_THREADS true
# define __VOLATILE volatile // Needed at -O3 on SGI
# endif /* __STL_SGI_THREADS */
# endif /* _NOTHREADS */
// Default node allocator.
// With a reasonable compiler, this should be roughly as fast as the
// original STL class-specific allocators, but with less fragmentation.
// Default_alloc_template parameters are experimental and MAY
// DISAPPEAR in the future. Clients should just use vcl_alloc for now.
//
// Important implementation properties:
// 1. If the client request an object of size > __MAX_BYTES, the resulting
// object will be obtained directly from malloc.
// 2. In all other cases, we allocate an object of size exactly
// ROUND_UP(requested_size). Thus the client has enough size
// information that we can return the object to the proper free vcl_list
// without permanently losing part of the object.
//
// The first template parameter specifies whether more than one thread
// may use this allocator. It is safe to allocate an object from
// one instance of a default_alloc and deallocate it with another
// one. This effectively transfers its ownership to the second one.
// This may have undesirable effects on reference locality.
// The second parameter is unreferenced and serves only to allow the
// creation of multiple default_alloc instances.
// Node that containers built on different allocator instances have
// different types, limiting the utility of this approach.
# if defined ( __SUNPRO_CC ) || defined ( _AIX )
// breaks if we make these template class members:
enum {__ALIGN = 8};
enum {__MAX_BYTES = 128};
enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
# endif
template <bool threads, int inst>
class __alloc
{
__PRIVATE:
// Really we should use static const int x = N
// instead of enum { x = N }, but few compilers accept the former.
# if ! (defined ( __SUNPRO_CC ) || defined ( _AIX ))
enum {__ALIGN = 8};
enum {__MAX_BYTES = 128};
enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
# endif
private:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?