Initial commit: ROW Client source code

Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 16:24:34 +09:00
commit e067522598
5135 changed files with 1745744 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOL_CT_GCD_LCM_HPP
#define BOOST_POOL_CT_GCD_LCM_HPP
#include <boost/static_assert.hpp>
#include <boost/type_traits/ice.hpp>
namespace boost {
namespace details {
namespace pool {
// Compile-time calculation of greatest common divisor and least common multiple
//
// ct_gcd is a compile-time algorithm that calculates the greatest common
// divisor of two unsigned integers, using Euclid's algorithm.
//
// assumes: A != 0 && B != 0
//
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
namespace details {
template <unsigned A, unsigned B, bool Bis0>
struct ct_gcd_helper;
template <unsigned A, unsigned B>
struct ct_gcd_helper<A, B, false>
{
BOOST_STATIC_CONSTANT(unsigned, A_mod_B_ = A % B);
BOOST_STATIC_CONSTANT(unsigned, value =
(::boost::details::pool::details::ct_gcd_helper<
B, static_cast<unsigned>(A_mod_B_),
::boost::type_traits::ice_eq<A_mod_B_, 0>::value
>::value) );
};
template <unsigned A, unsigned B>
struct ct_gcd_helper<A, B, true>
{
BOOST_STATIC_CONSTANT(unsigned, value = A);
};
} // namespace details
template <unsigned A, unsigned B>
struct ct_gcd
{
BOOST_STATIC_ASSERT(A != 0 && B != 0);
BOOST_STATIC_CONSTANT(unsigned, value =
(::boost::details::pool::details::ct_gcd_helper<A, B, false>::value) );
};
#else
// Thanks to Peter Dimov for providing this workaround!
namespace details {
template<unsigned A> struct ct_gcd2
{
template<unsigned B>
struct helper
{
BOOST_STATIC_CONSTANT(unsigned, value = ct_gcd2<B>::helper<A % B>::value);
};
template<>
struct helper<0>
{
BOOST_STATIC_CONSTANT(unsigned, value = A);
};
};
} // namespace details
template<unsigned A, unsigned B> struct ct_gcd
{
BOOST_STATIC_ASSERT(A != 0 && B != 0);
enum { value = details::ct_gcd2<A>::helper<B>::value };
};
#endif
//
// ct_lcm is a compile-time algorithm that calculates the least common
// multiple of two unsigned integers.
//
// assumes: A != 0 && B != 0
//
template <unsigned A, unsigned B>
struct ct_lcm
{
BOOST_STATIC_CONSTANT(unsigned, value =
(A / ::boost::details::pool::ct_gcd<A, B>::value * B) );
};
} // namespace pool
} // namespace details
} // namespace boost
#endif

View File

@@ -0,0 +1,107 @@
m4_dnl
m4_dnl Copyright (C) 2000 Stephen Cleary
m4_dnl
m4_dnl Distributed under the Boost Software License, Version 1.0. (See accompany-
m4_dnl ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
m4_dnl
m4_dnl See http://www.boost.org for updates, documentation, and revision history.
m4_dnl
m4_dnl
m4_dnl
m4_dnl BOOST_M4_FOR: repeat a given text for a range of values
m4_dnl $1 - variable to hold the current value.
m4_dnl $2 - the starting value.
m4_dnl $3 - the ending value (text is _not_ repeated for this value).
m4_dnl $4 - the text to repeat.
m4_dnl $5 - the delimeter text (optional).
m4_dnl
m4_dnl If the starting value is < ending value:
m4_dnl Will repeat $4, binding $1 to the values in the range [$2, $3).
m4_dnl Else (that is, starting value >= ending value):
m4_dnl Will do nothing
m4_dnl Repeats $5 in-between each occurrence of $4
m4_dnl
m4_dnl Logic:
m4_dnl Set $1 to $2 and call BOOST_M4_FOR_LIST_HELPER:
m4_dnl If $1 >= $3, do nothing
m4_dnl Else
m4_dnl output $4,
m4_dnl set $1 to itself incremented,
m4_dnl If $1 != $3, output $5,
m4_dnl and use recursion
m4_dnl
m4_define(`BOOST_M4_FOR',
`m4_ifelse(m4_eval($# < 4 || $# > 5), 1,
`m4_errprint(m4___file__:m4___line__: `Boost m4 script: BOOST_M4_FOR: Wrong number of arguments ($#)')',
`m4_pushdef(`$1', `$2')BOOST_M4_FOR_HELPER($@)m4_popdef(`$1')')')m4_dnl
m4_define(`BOOST_M4_FOR_HELPER',
`m4_ifelse(m4_eval($1 >= $3), 1, ,
`$4`'m4_define(`$1', m4_incr($1))m4_ifelse(m4_eval($1 != $3), 1, `$5')`'BOOST_M4_FOR_HELPER($@)')')m4_dnl
m4_dnl
m4_dnl Testing/Examples:
m4_dnl
m4_dnl The following line will output:
m4_dnl "repeat.m4:42: Boost m4 script: BOOST_M4_FOR: Wrong number of arguments (3)"
m4_dnl BOOST_M4_FOR(i, 1, 3)
m4_dnl
m4_dnl The following line will output:
m4_dnl "repeat.m4:46: Boost m4 script: BOOST_M4_FOR: Wrong number of arguments (6)"
m4_dnl BOOST_M4_FOR(i, 1, 3, i, ` ', 13)
m4_dnl
m4_dnl The following line will output (nothing):
m4_dnl ""
m4_dnl BOOST_M4_FOR(i, 7, 0, i )
m4_dnl
m4_dnl The following line will output (nothing):
m4_dnl ""
m4_dnl BOOST_M4_FOR(i, 0, 0, i )
m4_dnl
m4_dnl The following line will output:
m4_dnl "0 1 2 3 4 5 6 "
m4_dnl BOOST_M4_FOR(i, 0, 7, i )
m4_dnl
m4_dnl The following line will output:
m4_dnl "-13 -12 -11 "
m4_dnl BOOST_M4_FOR(i, -13, -10, i )
m4_dnl
m4_dnl The following two lines will output:
m4_dnl "(0, 0) (0, 1) (0, 2) (0, 3) "
m4_dnl "(1, 0) (1, 1) (1, 2) (1, 3) "
m4_dnl "(2, 0) (2, 1) (2, 2) (2, 3) "
m4_dnl "(3, 0) (3, 1) (3, 2) (3, 3) "
m4_dnl "(4, 0) (4, 1) (4, 2) (4, 3) "
m4_dnl "(5, 0) (5, 1) (5, 2) (5, 3) "
m4_dnl "(6, 0) (6, 1) (6, 2) (6, 3) "
m4_dnl "(7, 0) (7, 1) (7, 2) (7, 3) "
m4_dnl ""
m4_dnl BOOST_M4_FOR(i, 0, 8, BOOST_M4_FOR(j, 0, 4, (i, j) )
m4_dnl )
m4_dnl
m4_dnl The following line will output (nothing):
m4_dnl ""
m4_dnl BOOST_M4_FOR(i, 7, 0, i, |)
m4_dnl
m4_dnl The following line will output (nothing):
m4_dnl ""
m4_dnl BOOST_M4_FOR(i, 0, 0, i, |)
m4_dnl
m4_dnl The following line will output:
m4_dnl "0|1|2|3|4|5|6"
m4_dnl BOOST_M4_FOR(i, 0, 7, i, |)
m4_dnl
m4_dnl The following line will output:
m4_dnl "-13, -12, -11"
m4_dnl BOOST_M4_FOR(i, -13, -10, i, `, ')
m4_dnl
m4_dnl The following two lines will output:
m4_dnl "[(0, 0), (0, 1), (0, 2), (0, 3)],"
m4_dnl "[(1, 0), (1, 1), (1, 2), (1, 3)],"
m4_dnl "[(2, 0), (2, 1), (2, 2), (2, 3)],"
m4_dnl "[(3, 0), (3, 1), (3, 2), (3, 3)],"
m4_dnl "[(4, 0), (4, 1), (4, 2), (4, 3)],"
m4_dnl "[(5, 0), (5, 1), (5, 2), (5, 3)],"
m4_dnl "[(6, 0), (6, 1), (6, 2), (6, 3)],"
m4_dnl "[(7, 0), (7, 1), (7, 2), (7, 3)]"
m4_dnl BOOST_M4_FOR(i, 0, 8, `[BOOST_M4_FOR(j, 0, 4, (i, j), `, ')]', `,
m4_dnl ')
m4_dnl

View File

@@ -0,0 +1,58 @@
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOL_GCD_LCM_HPP
#define BOOST_POOL_GCD_LCM_HPP
namespace boost {
namespace details {
namespace pool {
// Greatest common divisor and least common multiple
//
// gcd is an algorithm that calculates the greatest common divisor of two
// integers, using Euclid's algorithm.
//
// Pre: A > 0 && B > 0
// Recommended: A > B
template <typename Integer>
Integer gcd(Integer A, Integer B)
{
do
{
const Integer tmp(B);
B = A % B;
A = tmp;
} while (B != 0);
return A;
}
//
// lcm is an algorithm that calculates the least common multiple of two
// integers.
//
// Pre: A > 0 && B > 0
// Recommended: A > B
template <typename Integer>
Integer lcm(const Integer & A, const Integer & B)
{
Integer ret = A;
ret /= gcd(A, B);
ret *= B;
return ret;
}
} // namespace pool
} // namespace details
} // namespace boost
#endif

View File

@@ -0,0 +1,40 @@
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOL_GUARD_HPP
#define BOOST_POOL_GUARD_HPP
// Extremely Light-Weight guard glass
namespace boost {
namespace details {
namespace pool {
template <typename Mutex>
class guard
{
private:
Mutex & mtx;
guard(const guard &);
void operator=(const guard &);
public:
explicit guard(Mutex & nmtx)
:mtx(nmtx) { mtx.lock(); }
~guard() { mtx.unlock(); }
};
} // namespace pool
} // namespace details
} // namespace boost
#endif

View File

@@ -0,0 +1,145 @@
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOL_MUTEX_HPP
#define BOOST_POOL_MUTEX_HPP
#include <boost/config.hpp> // for workarounds
// Extremely Light-Weight wrapper classes for OS thread synchronization
// Configuration: for now, we just choose between pthread or Win32 mutexes or none
#define BOOST_MUTEX_HELPER_NONE 0
#define BOOST_MUTEX_HELPER_WIN32 1
#define BOOST_MUTEX_HELPER_PTHREAD 2
#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
# define BOOST_NO_MT
#endif
#ifdef BOOST_NO_MT
// No multithreading -> make locks into no-ops
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
#else
#ifdef BOOST_WINDOWS
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
#else
#include <unistd.h>
#ifdef _POSIX_THREADS
#define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
#endif
#endif
#endif
#ifndef BOOST_MUTEX_HELPER
#error Unable to determine platform mutex type; define BOOST_NO_MT to assume single-threaded
#endif
#ifndef BOOST_NO_MT
# ifdef BOOST_WINDOWS
# include <windows.h>
# endif
# ifdef _POSIX_THREADS
# include <pthread.h>
# endif
#endif
namespace boost {
namespace details {
namespace pool {
#ifndef BOOST_NO_MT
#ifdef BOOST_WINDOWS
class win32_mutex
{
private:
CRITICAL_SECTION mtx;
win32_mutex(const win32_mutex &);
void operator=(const win32_mutex &);
public:
win32_mutex()
{ InitializeCriticalSection(&mtx); }
~win32_mutex()
{ DeleteCriticalSection(&mtx); }
void lock()
{ EnterCriticalSection(&mtx); }
void unlock()
{ LeaveCriticalSection(&mtx); }
};
#endif // defined(BOOST_WINDOWS)
#ifdef _POSIX_THREADS
class pthread_mutex
{
private:
pthread_mutex_t mtx;
pthread_mutex(const pthread_mutex &);
void operator=(const pthread_mutex &);
public:
pthread_mutex()
{ pthread_mutex_init(&mtx, 0); }
~pthread_mutex()
{ pthread_mutex_destroy(&mtx); }
void lock()
{ pthread_mutex_lock(&mtx); }
void unlock()
{ pthread_mutex_unlock(&mtx); }
};
#endif // defined(_POSIX_THREADS)
#endif // !defined(BOOST_NO_MT)
class null_mutex
{
private:
null_mutex(const null_mutex &);
void operator=(const null_mutex &);
public:
null_mutex() { }
static void lock() { }
static void unlock() { }
};
#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
typedef null_mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
typedef win32_mutex default_mutex;
#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
typedef pthread_mutex default_mutex;
#endif
} // namespace pool
} // namespace details
} // namespace boost
#undef BOOST_MUTEX_HELPER_WIN32
#undef BOOST_MUTEX_HELPER_PTHREAD
#undef BOOST_MUTEX_HELPER_NONE
#undef BOOST_MUTEX_HELPER
#endif

View File

@@ -0,0 +1,24 @@
@echo off
rem
rem Copyright (C) 2000, 2001 Stephen Cleary
rem
rem Distributed under the Boost Software License, Version 1.0. (See accompany-
rem ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
rem Check for Windows NT
if %OS%==Windows_NT goto NT
rem Not NT - run m4 as normal, then exit
m4 -P -E -DNumberOfArguments=%1 pool_construct.m4 > pool_construct.inc
goto end
rem DJGPP programs (including m4) running on Windows/NT do NOT support long
rem file names (see the DJGPP v2 FAQ, question 8.1)
rem Note that the output doesn't have to be a short name because it's an
rem argument to the command shell, not m4.
:NT
m4 -P -E -DNumberOfArguments=%1 < pool_construct.m4 > pool_construct.inc
:end

View File

@@ -0,0 +1,853 @@
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
// This file was AUTOMATICALLY GENERATED from "pool_c~1.m4"
// Do NOT include directly!
// Do NOT edit!
template <typename T0>
element_type * construct(T0 & a0)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0>
element_type * construct(const T0 & a0)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0>
element_type * construct(volatile T0 & a0)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0>
element_type * construct(const volatile T0 & a0)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(T0 & a0, T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const T0 & a0, T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(volatile T0 & a0, T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const volatile T0 & a0, T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(T0 & a0, const T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const T0 & a0, const T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(volatile T0 & a0, const T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const volatile T0 & a0, const T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(T0 & a0, volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const T0 & a0, volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(volatile T0 & a0, volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const volatile T0 & a0, volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(T0 & a0, const volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const T0 & a0, const volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(volatile T0 & a0, const volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const volatile T0 & a0, const volatile T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const volatile T1 & a1, T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const volatile T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const volatile T1 & a1, volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(volatile T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const volatile T0 & a0, const volatile T1 & a1, const volatile T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}

View File

@@ -0,0 +1,84 @@
m4_dnl
m4_dnl Copyright (C) 2000 Stephen Cleary
m4_dnl
m4_dnl Distributed under the Boost Software License, Version 1.0. (See accompany-
m4_dnl ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
m4_dnl
m4_dnl See http://www.boost.org for updates, documentation, and revision history.
m4_dnl
m4_dnl
m4_dnl
m4_dnl Avoid the use of any m4_* identifiers in this header file,
m4_dnl as that may cause incompatibility problems with future
m4_dnl versions of m4.
m4_dnl
m4_dnl This is a normal header file, except that lines starting
m4_dnl with `m4_dnl' will be stripped, TBA_FOR
m4_dnl macros will be replaced with repeated text, and text in
m4_dnl single quotes (`...') will have their single quotes
m4_dnl stripped.
m4_dnl
m4_dnl
m4_dnl Check to make sure NumberOfArguments was defined. If it's not defined,
m4_dnl default to 3
m4_dnl
m4_ifdef(`NumberOfArguments', , `m4_errprint(m4___file__:m4___line__`: NumberOfArguments is not defined; defaulting to 3
')m4_define(`NumberOfArguments', 3)')m4_dnl
m4_ifelse(NumberOfArguments, , `m4_errprint(m4___file__:m4___line__`: NumberOfArguments is defined to be empty; defaulting to 3
')m4_define(`NumberOfArguments', 3)')m4_dnl
m4_dnl
m4_dnl Check to make sure NumberOfArguments >= 1. If it's not, then fatal error.
m4_dnl
m4_ifelse(m4_eval(NumberOfArguments < 1), 1, `m4_errprint(m4___file__:m4___line__`: NumberOfArguments ('NumberOfArguments`) is less than 1
')m4_m4exit(1)')m4_dnl
m4_dnl
m4_dnl Include the BOOST_M4_FOR macro definition
m4_dnl
m4_include(`for.m4')`'m4_dnl
m4_dnl
m4_dnl Begin the generated file.
m4_dnl
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See accompany-
// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
m4_dnl These warnings apply to the file generated from this file.
m4_dnl Of course, you may freely edit this file.
// This file was AUTOMATICALLY GENERATED from "m4___file__"
// Do NOT include directly!
// Do NOT edit!
m4_dnl
m4_dnl First we define a simple 'cv_qual' macro which takes a number, either
m4_dnl 0, 1, 2, or 3, and determines cv-qualification.
m4_dnl
m4_define(`cv_qual',
`m4_ifelse($1, 0, `',
`m4_ifelse($1, 1, `const ',
`m4_ifelse($1, 2, `volatile ',
`m4_ifelse($1, 3, `const volatile ',
`m4_errprint(m4___file__:m4___line__: `Boost m4 script: cv-determiner: Not 0, 1, 2, or 3 (was '$1`)')'
)')')')')m4_dnl
m4_dnl
m4_dnl Next we go through the actual loop. For each number of arguments from
m4_dnl 1 to NumberOfArguments, we create a template function that takes that
m4_dnl many template arguments, and also generate all cv-qualified permutations
m4_dnl of that function.
m4_dnl
BOOST_M4_FOR(N, 1, NumberOfArguments + 1,
`BOOST_M4_FOR(cv, 0, m4_eval(4 ** N),
`template <BOOST_M4_FOR(i, 0, N, `typename T`'i', `, ')>
element_type * construct(BOOST_M4_FOR(i, 0, N,
`cv_qual(m4_eval((cv >> (i * 2)) % 4))T`'i & a`'i', `, '))
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(BOOST_M4_FOR(i, 0, N, `a`'i', `, ')); }
catch (...) { free(ret); throw; }
return ret;
}
')')

View File

@@ -0,0 +1,11 @@
#!/bin/sh
#
# Copyright (C) 2000 Stephen Cleary
#
# Distributed under the Boost Software License, Version 1.0. (See accompany-
# ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org for updates, documentation, and revision history.
#
m4 -P -E -DNumberOfArguments=$1 pool_construct.m4 > pool_construct.inc

View File

@@ -0,0 +1,25 @@
@echo off
rem
rem Copyright (C) 2001 Stephen Cleary
rem
rem Distributed under the Boost Software License, Version 1.0. (See accompany-
rem ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
rem
rem See http://www.boost.org for updates, documentation, and revision history.
rem
rem Check for Windows NT
if %OS%==Windows_NT goto NT
rem Not NT - run m4 as normal, then exit
m4 -P -E -DNumberOfArguments=%1 pool_construct_simple.m4 > pool_construct_simple.inc
goto end
rem DJGPP programs (including m4) running on Windows/NT do NOT support long
rem file names (see the DJGPP v2 FAQ, question 8.1)
rem Note that the output doesn't have to be a short name because it's an
rem argument to the command shell, not m4.
:NT
m4 -P -E -DNumberOfArguments=%1 < pool_construct_simple.m4 > pool_construct_simple.inc
:end

View File

@@ -0,0 +1,43 @@
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
// This file was AUTOMATICALLY GENERATED from "stdin"
// Do NOT include directly!
// Do NOT edit!
template <typename T0>
element_type * construct(const T0 & a0)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1>
element_type * construct(const T0 & a0, const T1 & a1)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1); }
catch (...) { free(ret); throw; }
return ret;
}
template <typename T0, typename T1, typename T2>
element_type * construct(const T0 & a0, const T1 & a1, const T2 & a2)
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(a0, a1, a2); }
catch (...) { free(ret); throw; }
return ret;
}

View File

@@ -0,0 +1,73 @@
m4_dnl
m4_dnl Copyright (C) 2001 Stephen Cleary
m4_dnl
m4_dnl Distributed under the Boost Software License, Version 1.0. (See accompany-
m4_dnl ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
m4_dnl
m4_dnl See http://www.boost.org for updates, documentation, and revision history.
m4_dnl
m4_dnl
m4_dnl
m4_dnl Avoid the use of any m4_* identifiers in this header file,
m4_dnl as that may cause incompatibility problems with future
m4_dnl versions of m4.
m4_dnl
m4_dnl This is a normal header file, except that lines starting
m4_dnl with `m4_dnl' will be stripped, TBA_FOR
m4_dnl macros will be replaced with repeated text, and text in
m4_dnl single quotes (`...') will have their single quotes
m4_dnl stripped.
m4_dnl
m4_dnl
m4_dnl Check to make sure NumberOfArguments was defined. If it's not defined,
m4_dnl default to 3
m4_dnl
m4_ifdef(`NumberOfArguments', , `m4_errprint(m4___file__:m4___line__`: NumberOfArguments is not defined; defaulting to 3
')m4_define(`NumberOfArguments', 3)')m4_dnl
m4_ifelse(NumberOfArguments, , `m4_errprint(m4___file__:m4___line__`: NumberOfArguments is defined to be empty; defaulting to 3
')m4_define(`NumberOfArguments', 3)')m4_dnl
m4_dnl
m4_dnl Check to make sure NumberOfArguments >= 1. If it's not, then fatal error.
m4_dnl
m4_ifelse(m4_eval(NumberOfArguments < 1), 1, `m4_errprint(m4___file__:m4___line__`: NumberOfArguments ('NumberOfArguments`) is less than 1
')m4_m4exit(1)')m4_dnl
m4_dnl
m4_dnl Include the BOOST_M4_FOR macro definition
m4_dnl
m4_include(`for.m4')`'m4_dnl
m4_dnl
m4_dnl Begin the generated file.
m4_dnl
// Copyright (C) 2000 Stephen Cleary
//
// This file can be redistributed and/or modified under the terms found
// in "copyright.html"
// This software and its documentation is provided "as is" without express or
// implied warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org for updates, documentation, and revision history.
m4_dnl These warnings apply to the file generated from this file.
m4_dnl Of course, you may freely edit this file.
// This file was AUTOMATICALLY GENERATED from "m4___file__"
// Do NOT include directly!
// Do NOT edit!
m4_dnl
m4_dnl Here we go through the actual loop. For each number of arguments from
m4_dnl 1 to NumberOfArguments, we create a template function that takes that
m4_dnl many template arguments.
m4_dnl
BOOST_M4_FOR(N, 1, NumberOfArguments + 1,
`template <BOOST_M4_FOR(i, 0, N, `typename T`'i', `, ')>
element_type * construct(BOOST_M4_FOR(i, 0, N,
`const T`'i & a`'i', `, '))
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(BOOST_M4_FOR(i, 0, N, `a`'i', `, ')); }
catch (...) { free(ret); throw; }
return ret;
}
')

View File

@@ -0,0 +1,11 @@
#!/bin/sh
#
# Copyright (C) 2001 Stephen Cleary
#
# Distributed under the Boost Software License, Version 1.0. (See accompany-
# ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org for updates, documentation, and revision history.
#
m4 -P -E -DNumberOfArguments=$1 pool_construct_simple.m4 > pool_construct_simple.inc

View File

@@ -0,0 +1,107 @@
// Copyright (C) 2000 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOL_SINGLETON_HPP
#define BOOST_POOL_SINGLETON_HPP
// The following code might be put into some Boost.Config header in a later revision
#ifdef __BORLANDC__
# pragma option push -w-inl
#endif
//
// The following helper classes are placeholders for a generic "singleton"
// class. The classes below support usage of singletons, including use in
// program startup/shutdown code, AS LONG AS there is only one thread
// running before main() begins, and only one thread running after main()
// exits.
//
// This class is also limited in that it can only provide singleton usage for
// classes with default constructors.
//
// The design of this class is somewhat twisted, but can be followed by the
// calling inheritance. Let us assume that there is some user code that
// calls "singleton_default<T>::instance()". The following (convoluted)
// sequence ensures that the same function will be called before main():
// instance() contains a call to create_object.do_nothing()
// Thus, object_creator is implicitly instantiated, and create_object
// must exist.
// Since create_object is a static member, its constructor must be
// called before main().
// The constructor contains a call to instance(), thus ensuring that
// instance() will be called before main().
// The first time instance() is called (i.e., before main()) is the
// latest point in program execution where the object of type T
// can be created.
// Thus, any call to instance() will auto-magically result in a call to
// instance() before main(), unless already present.
// Furthermore, since the instance() function contains the object, instead
// of the singleton_default class containing a static instance of the
// object, that object is guaranteed to be constructed (at the latest) in
// the first call to instance(). This permits calls to instance() from
// static code, even if that code is called before the file-scope objects
// in this file have been initialized.
namespace boost {
namespace details {
namespace pool {
// T must be: no-throw default constructible and no-throw destructible
template <typename T>
struct singleton_default
{
private:
struct object_creator
{
// This constructor does nothing more than ensure that instance()
// is called before main() begins, thus creating the static
// T object before multithreading race issues can come up.
object_creator() { singleton_default<T>::instance(); }
inline void do_nothing() const { }
};
static object_creator create_object;
singleton_default();
public:
typedef T object_type;
// If, at any point (in user code), singleton_default<T>::instance()
// is called, then the following function is instantiated.
static object_type & instance()
{
// This is the object that we return a reference to.
// It is guaranteed to be created before main() begins because of
// the next line.
static object_type obj;
// The following line does nothing else than force the instantiation
// of singleton_default<T>::create_object, whose constructor is
// called before main() begins.
create_object.do_nothing();
return obj;
}
};
template <typename T>
typename singleton_default<T>::object_creator
singleton_default<T>::create_object;
} // namespace pool
} // namespace details
} // namespace boost
// The following code might be put into some Boost.Config header in a later revision
#ifdef __BORLANDC__
# pragma option pop
#endif
#endif

View File

@@ -0,0 +1,157 @@
// Copyright (C) 2000, 2001 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_OBJECT_POOL_HPP
#define BOOST_OBJECT_POOL_HPP
#include <boost/pool/poolfwd.hpp>
// boost::pool
#include <boost/pool/pool.hpp>
// The following code will be put into Boost.Config in a later revision
#if defined(BOOST_MSVC) || defined(__KCC)
# define BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
#endif
// The following code might be put into some Boost.Config header in a later revision
#ifdef __BORLANDC__
# pragma option push -w-inl
#endif
// There are a few places in this file where the expression "this->m" is used.
// This expression is used to force instantiation-time name lookup, which I am
// informed is required for strict Standard compliance. It's only necessary
// if "m" is a member of a base class that is dependent on a template
// parameter.
// Thanks to Jens Maurer for pointing this out!
namespace boost {
// T must have a non-throwing destructor
template <typename T, typename UserAllocator>
class object_pool: protected pool<UserAllocator>
{
public:
typedef T element_type;
typedef UserAllocator user_allocator;
typedef typename pool<UserAllocator>::size_type size_type;
typedef typename pool<UserAllocator>::difference_type difference_type;
protected:
pool<UserAllocator> & store() { return *this; }
const pool<UserAllocator> & store() const { return *this; }
// for the sake of code readability :)
static void * & nextof(void * const ptr)
{ return *(static_cast<void **>(ptr)); }
public:
// This constructor parameter is an extension!
explicit object_pool(const size_type next_size = 32)
:pool<UserAllocator>(sizeof(T), next_size) { }
~object_pool();
// Returns 0 if out-of-memory
element_type * malloc()
{ return static_cast<element_type *>(store().ordered_malloc()); }
void free(element_type * const chunk)
{ store().ordered_free(chunk); }
bool is_from(element_type * const chunk) const
{ return store().is_from(chunk); }
element_type * construct()
{
element_type * const ret = malloc();
if (ret == 0)
return ret;
try { new (ret) element_type(); }
catch (...) { free(ret); throw; }
return ret;
}
// Include automatically-generated file for family of template construct()
// functions
#ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
# include <boost/pool/detail/pool_construct.inc>
#else
# include <boost/pool/detail/pool_construct_simple.inc>
#endif
void destroy(element_type * const chunk)
{
chunk->~T();
free(chunk);
}
// These functions are extensions!
size_type get_next_size() const { return store().get_next_size(); }
void set_next_size(const size_type x) { store().set_next_size(x); }
};
template <typename T, typename UserAllocator>
object_pool<T, UserAllocator>::~object_pool()
{
// handle trivial case
if (!this->list.valid())
return;
details::PODptr<size_type> iter = this->list;
details::PODptr<size_type> next = iter;
// Start 'freed_iter' at beginning of free list
void * freed_iter = this->first;
const size_type partition_size = this->alloc_size();
do
{
// increment next
next = next.next();
// delete all contained objects that aren't freed
// Iterate 'i' through all chunks in the memory block
for (char * i = iter.begin(); i != iter.end(); i += partition_size)
{
// If this chunk is free
if (i == freed_iter)
{
// Increment freed_iter to point to next in free list
freed_iter = nextof(freed_iter);
// Continue searching chunks in the memory block
continue;
}
// This chunk is not free (allocated), so call its destructor
static_cast<T *>(static_cast<void *>(i))->~T();
// and continue searching chunks in the memory block
}
// free storage
UserAllocator::free(iter.begin());
// increment iter
iter = next;
} while (iter.valid());
// Make the block list empty so that the inherited destructor doesn't try to
// free it again.
this->list.invalidate();
}
} // namespace boost
// The following code might be put into some Boost.Config header in a later revision
#ifdef __BORLANDC__
# pragma option pop
#endif
#endif

View File

@@ -0,0 +1,580 @@
// Copyright (C) 2000, 2001 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOL_HPP
#define BOOST_POOL_HPP
#include <boost/config.hpp> // for workarounds
// std::less, std::less_equal, std::greater
#include <functional>
// new[], delete[], std::nothrow
#include <new>
// std::size_t, std::ptrdiff_t
#include <cstddef>
// std::malloc, std::free
#include <cstdlib>
// std::invalid_argument
#include <exception>
// std::max
#include <algorithm>
#include <boost/pool/poolfwd.hpp>
// boost::details::pool::ct_lcm
#include <boost/pool/detail/ct_gcd_lcm.hpp>
// boost::details::pool::lcm
#include <boost/pool/detail/gcd_lcm.hpp>
// boost::simple_segregated_storage
#include <boost/pool/simple_segregated_storage.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::malloc; using ::free; }
#endif
// There are a few places in this file where the expression "this->m" is used.
// This expression is used to force instantiation-time name lookup, which I am
// informed is required for strict Standard compliance. It's only necessary
// if "m" is a member of a base class that is dependent on a template
// parameter.
// Thanks to Jens Maurer for pointing this out!
namespace boost {
struct default_user_allocator_new_delete
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static char * malloc(const size_type bytes)
{ return new (std::nothrow) char[bytes]; }
static void free(char * const block)
{ delete [] block; }
};
struct default_user_allocator_malloc_free
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static char * malloc(const size_type bytes)
{ return reinterpret_cast<char *>(std::malloc(bytes)); }
static void free(char * const block)
{ std::free(block); }
};
namespace details {
// PODptr is a class that pretends to be a "pointer" to different class types
// that don't really exist. It provides member functions to access the "data"
// of the "object" it points to. Since these "class" types are of variable
// size, and contains some information at the *end* of its memory (for
// alignment reasons), PODptr must contain the size of this "class" as well as
// the pointer to this "object".
template <typename SizeType>
class PODptr
{
public:
typedef SizeType size_type;
private:
char * ptr;
size_type sz;
char * ptr_next_size() const
{ return (ptr + sz - sizeof(size_type)); }
char * ptr_next_ptr() const
{
return (ptr_next_size() -
pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);
}
public:
PODptr(char * const nptr, const size_type nsize)
:ptr(nptr), sz(nsize) { }
PODptr()
:ptr(0), sz(0) { }
bool valid() const { return (begin() != 0); }
void invalidate() { begin() = 0; }
char * & begin() { return ptr; }
char * begin() const { return ptr; }
char * end() const { return ptr_next_ptr(); }
size_type total_size() const { return sz; }
size_type element_size() const
{
return (sz - sizeof(size_type) -
pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value);
}
size_type & next_size() const
{ return *(reinterpret_cast<size_type *>(ptr_next_size())); }
char * & next_ptr() const
{ return *(reinterpret_cast<char **>(ptr_next_ptr())); }
PODptr next() const
{ return PODptr<size_type>(next_ptr(), next_size()); }
void next(const PODptr & arg) const
{
next_ptr() = arg.begin();
next_size() = arg.total_size();
}
};
} // namespace details
template <typename UserAllocator>
class pool: protected simple_segregated_storage<
typename UserAllocator::size_type>
{
public:
typedef UserAllocator user_allocator;
typedef typename UserAllocator::size_type size_type;
typedef typename UserAllocator::difference_type difference_type;
private:
BOOST_STATIC_CONSTANT(unsigned, min_alloc_size =
(::boost::details::pool::ct_lcm<sizeof(void *), sizeof(size_type)>::value) );
// Returns 0 if out-of-memory
// Called if malloc/ordered_malloc needs to resize the free list
void * malloc_need_resize();
void * ordered_malloc_need_resize();
protected:
details::PODptr<size_type> list;
simple_segregated_storage<size_type> & store() { return *this; }
const simple_segregated_storage<size_type> & store() const { return *this; }
const size_type requested_size;
size_type next_size;
// finds which POD in the list 'chunk' was allocated from
details::PODptr<size_type> find_POD(void * const chunk) const;
// is_from() tests a chunk to determine if it belongs in a block
static bool is_from(void * const chunk, char * const i,
const size_type sizeof_i)
{
// We use std::less_equal and std::less to test 'chunk'
// against the array bounds because standard operators
// may return unspecified results.
// This is to ensure portability. The operators < <= > >= are only
// defined for pointers to objects that are 1) in the same array, or
// 2) subobjects of the same object [5.9/2].
// The functor objects guarantee a total order for any pointer [20.3.3/8]
//WAS:
// return (std::less_equal<void *>()(static_cast<void *>(i), chunk)
// && std::less<void *>()(chunk,
// static_cast<void *>(i + sizeof_i)));
std::less_equal<void *> lt_eq;
std::less<void *> lt;
return (lt_eq(i, chunk) && lt(chunk, i + sizeof_i));
}
size_type alloc_size() const
{
const unsigned min_size = min_alloc_size;
return details::pool::lcm<size_type>(requested_size, min_size);
}
// for the sake of code readability :)
static void * & nextof(void * const ptr)
{ return *(static_cast<void **>(ptr)); }
public:
// The second parameter here is an extension!
// pre: npartition_size != 0 && nnext_size != 0
explicit pool(const size_type nrequested_size,
const size_type nnext_size = 32)
:list(0, 0), requested_size(nrequested_size), next_size(nnext_size)
{ }
~pool() { purge_memory(); }
// Releases memory blocks that don't have chunks allocated
// pre: lists are ordered
// Returns true if memory was actually deallocated
bool release_memory();
// Releases *all* memory blocks, even if chunks are still allocated
// Returns true if memory was actually deallocated
bool purge_memory();
// These functions are extensions!
size_type get_next_size() const { return next_size; }
void set_next_size(const size_type nnext_size) { next_size = nnext_size; }
// Both malloc and ordered_malloc do a quick inlined check first for any
// free chunks. Only if we need to get another memory block do we call
// the non-inlined *_need_resize() functions.
// Returns 0 if out-of-memory
void * malloc()
{
// Look for a non-empty storage
if (!store().empty())
return store().malloc();
return malloc_need_resize();
}
void * ordered_malloc()
{
// Look for a non-empty storage
if (!store().empty())
return store().malloc();
return ordered_malloc_need_resize();
}
// Returns 0 if out-of-memory
// Allocate a contiguous section of n chunks
void * ordered_malloc(size_type n);
// pre: 'chunk' must have been previously
// returned by *this.malloc().
void free(void * const chunk)
{ store().free(chunk); }
// pre: 'chunk' must have been previously
// returned by *this.malloc().
void ordered_free(void * const chunk)
{ store().ordered_free(chunk); }
// pre: 'chunk' must have been previously
// returned by *this.malloc(n).
void free(void * const chunks, const size_type n)
{
const size_type partition_size = alloc_size();
const size_type total_req_size = n * requested_size;
const size_type num_chunks = total_req_size / partition_size +
((total_req_size % partition_size) ? true : false);
store().free_n(chunks, num_chunks, partition_size);
}
// pre: 'chunk' must have been previously
// returned by *this.malloc(n).
void ordered_free(void * const chunks, const size_type n)
{
const size_type partition_size = alloc_size();
const size_type total_req_size = n * requested_size;
const size_type num_chunks = total_req_size / partition_size +
((total_req_size % partition_size) ? true : false);
store().ordered_free_n(chunks, num_chunks, partition_size);
}
// is_from() tests a chunk to determine if it was allocated from *this
bool is_from(void * const chunk) const
{
return (find_POD(chunk).valid());
}
};
template <typename UserAllocator>
bool pool<UserAllocator>::release_memory()
{
// This is the return value: it will be set to true when we actually call
// UserAllocator::free(..)
bool ret = false;
// This is a current & previous iterator pair over the memory block list
details::PODptr<size_type> ptr = list;
details::PODptr<size_type> prev;
// This is a current & previous iterator pair over the free memory chunk list
// Note that "prev_free" in this case does NOT point to the previous memory
// chunk in the free list, but rather the last free memory chunk before the
// current block.
void * free = this->first;
void * prev_free = 0;
const size_type partition_size = alloc_size();
// Search through all the all the allocated memory blocks
while (ptr.valid())
{
// At this point:
// ptr points to a valid memory block
// free points to either:
// 0 if there are no more free chunks
// the first free chunk in this or some next memory block
// prev_free points to either:
// the last free chunk in some previous memory block
// 0 if there is no such free chunk
// prev is either:
// the PODptr whose next() is ptr
// !valid() if there is no such PODptr
// If there are no more free memory chunks, then every remaining
// block is allocated out to its fullest capacity, and we can't
// release any more memory
if (free == 0)
return ret;
// We have to check all the chunks. If they are *all* free (i.e., present
// in the free list), then we can free the block.
bool all_chunks_free = true;
// Iterate 'i' through all chunks in the memory block
// if free starts in the memory block, be careful to keep it there
void * saved_free = free;
for (char * i = ptr.begin(); i != ptr.end(); i += partition_size)
{
// If this chunk is not free
if (i != free)
{
// We won't be able to free this block
all_chunks_free = false;
// free might have travelled outside ptr
free = saved_free;
// Abort searching the chunks; we won't be able to free this
// block because a chunk is not free.
break;
}
// We do not increment prev_free because we are in the same block
free = nextof(free);
}
// post: if the memory block has any chunks, free points to one of them
// otherwise, our assertions above are still valid
const details::PODptr<size_type> next = ptr.next();
if (!all_chunks_free)
{
if (is_from(free, ptr.begin(), ptr.element_size()))
{
std::less<void *> lt;
void * const end = ptr.end();
do
{
prev_free = free;
free = nextof(free);
} while (free && lt(free, end));
}
// This invariant is now restored:
// free points to the first free chunk in some next memory block, or
// 0 if there is no such chunk.
// prev_free points to the last free chunk in this memory block.
// We are just about to advance ptr. Maintain the invariant:
// prev is the PODptr whose next() is ptr, or !valid()
// if there is no such PODptr
prev = ptr;
}
else
{
// All chunks from this block are free
// Remove block from list
if (prev.valid())
prev.next(next);
else
list = next;
// Remove all entries in the free list from this block
if (prev_free != 0)
nextof(prev_free) = free;
else
this->first = free;
// And release memory
UserAllocator::free(ptr.begin());
ret = true;
}
// Increment ptr
ptr = next;
}
return ret;
}
template <typename UserAllocator>
bool pool<UserAllocator>::purge_memory()
{
details::PODptr<size_type> iter = list;
if (!iter.valid())
return false;
do
{
// hold "next" pointer
const details::PODptr<size_type> next = iter.next();
// delete the storage
UserAllocator::free(iter.begin());
// increment iter
iter = next;
} while (iter.valid());
list.invalidate();
this->first = 0;
return true;
}
template <typename UserAllocator>
void * pool<UserAllocator>::malloc_need_resize()
{
// No memory in any of our storages; make a new storage,
const size_type partition_size = alloc_size();
const size_type POD_size = next_size * partition_size +
details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
char * const ptr = UserAllocator::malloc(POD_size);
if (ptr == 0)
return 0;
const details::PODptr<size_type> node(ptr, POD_size);
next_size <<= 1;
// initialize it,
store().add_block(node.begin(), node.element_size(), partition_size);
// insert it into the list,
node.next(list);
list = node;
// and return a chunk from it.
return store().malloc();
}
template <typename UserAllocator>
void * pool<UserAllocator>::ordered_malloc_need_resize()
{
// No memory in any of our storages; make a new storage,
const size_type partition_size = alloc_size();
const size_type POD_size = next_size * partition_size +
details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
char * const ptr = UserAllocator::malloc(POD_size);
if (ptr == 0)
return 0;
const details::PODptr<size_type> node(ptr, POD_size);
next_size <<= 1;
// initialize it,
// (we can use "add_block" here because we know that
// the free list is empty, so we don't have to use
// the slower ordered version)
store().add_block(node.begin(), node.element_size(), partition_size);
// insert it into the list,
// handle border case
if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))
{
node.next(list);
list = node;
}
else
{
details::PODptr<size_type> prev = list;
while (true)
{
// if we're about to hit the end or
// if we've found where "node" goes
if (prev.next_ptr() == 0
|| std::greater<void *>()(prev.next_ptr(), node.begin()))
break;
prev = prev.next();
}
node.next(prev.next());
prev.next(node);
}
// and return a chunk from it.
return store().malloc();
}
template <typename UserAllocator>
void * pool<UserAllocator>::ordered_malloc(const size_type n)
{
const size_type partition_size = alloc_size();
const size_type total_req_size = n * requested_size;
const size_type num_chunks = total_req_size / partition_size +
((total_req_size % partition_size) ? true : false);
void * ret = store().malloc_n(num_chunks, partition_size);
if (ret != 0)
return ret;
// Not enougn memory in our storages; make a new storage,
BOOST_USING_STD_MAX();
next_size = max BOOST_PREVENT_MACRO_SUBSTITUTION(next_size, num_chunks);
const size_type POD_size = next_size * partition_size +
details::pool::ct_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type);
char * const ptr = UserAllocator::malloc(POD_size);
if (ptr == 0)
return 0;
const details::PODptr<size_type> node(ptr, POD_size);
// Split up block so we can use what wasn't requested
// (we can use "add_block" here because we know that
// the free list is empty, so we don't have to use
// the slower ordered version)
if (next_size > num_chunks)
store().add_block(node.begin() + num_chunks * partition_size,
node.element_size() - num_chunks * partition_size, partition_size);
next_size <<= 1;
// insert it into the list,
// handle border case
if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))
{
node.next(list);
list = node;
}
else
{
details::PODptr<size_type> prev = list;
while (true)
{
// if we're about to hit the end or
// if we've found where "node" goes
if (prev.next_ptr() == 0
|| std::greater<void *>()(prev.next_ptr(), node.begin()))
break;
prev = prev.next();
}
node.next(prev.next());
prev.next(node);
}
// and return it.
return node.begin();
}
template <typename UserAllocator>
details::PODptr<typename pool<UserAllocator>::size_type>
pool<UserAllocator>::find_POD(void * const chunk) const
{
// We have to find which storage this chunk is from.
details::PODptr<size_type> iter = list;
while (iter.valid())
{
if (is_from(chunk, iter.begin(), iter.element_size()))
return iter;
iter = iter.next();
}
return iter;
}
} // namespace boost
#endif

View File

@@ -0,0 +1,221 @@
// Copyright (C) 2000, 2001 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOL_ALLOC_HPP
#define BOOST_POOL_ALLOC_HPP
// std::numeric_limits
#include <boost/limits.hpp>
// new, std::bad_alloc
#include <new>
#include <boost/pool/poolfwd.hpp>
// boost::singleton_pool
#include <boost/pool/singleton_pool.hpp>
#include <boost/detail/workaround.hpp>
// The following code will be put into Boost.Config in a later revision
#if defined(_RWSTD_VER) || defined(__SGI_STL_PORT) || \
BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
#define BOOST_NO_PROPER_STL_DEALLOCATE
#endif
namespace boost {
struct pool_allocator_tag { };
template <typename T,
typename UserAllocator,
typename Mutex,
unsigned NextSize>
class pool_allocator
{
public:
typedef T value_type;
typedef UserAllocator user_allocator;
typedef Mutex mutex;
BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
typedef value_type * pointer;
typedef const value_type * const_pointer;
typedef value_type & reference;
typedef const value_type & const_reference;
typedef typename pool<UserAllocator>::size_type size_type;
typedef typename pool<UserAllocator>::difference_type difference_type;
template <typename U>
struct rebind
{
typedef pool_allocator<U, UserAllocator, Mutex, NextSize> other;
};
public:
pool_allocator() { }
// default copy constructor
// default assignment operator
// not explicit, mimicking std::allocator [20.4.1]
template <typename U>
pool_allocator(const pool_allocator<U, UserAllocator, Mutex, NextSize> &)
{ }
// default destructor
static pointer address(reference r)
{ return &r; }
static const_pointer address(const_reference s)
{ return &s; }
static size_type max_size()
{ return (std::numeric_limits<size_type>::max)(); }
static void construct(const pointer ptr, const value_type & t)
{ new (ptr) T(t); }
static void destroy(const pointer ptr)
{
ptr->~T();
(void) ptr; // avoid unused variable warning
}
bool operator==(const pool_allocator &) const
{ return true; }
bool operator!=(const pool_allocator &) const
{ return false; }
static pointer allocate(const size_type n)
{
const pointer ret = static_cast<pointer>(
singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
NextSize>::ordered_malloc(n) );
if (ret == 0)
throw std::bad_alloc();
return ret;
}
static pointer allocate(const size_type n, const void * const)
{ return allocate(n); }
static void deallocate(const pointer ptr, const size_type n)
{
#ifdef BOOST_NO_PROPER_STL_DEALLOCATE
if (ptr == 0 || n == 0)
return;
#endif
singleton_pool<pool_allocator_tag, sizeof(T), UserAllocator, Mutex,
NextSize>::ordered_free(ptr, n);
}
};
struct fast_pool_allocator_tag { };
template <typename T,
typename UserAllocator,
typename Mutex,
unsigned NextSize>
class fast_pool_allocator
{
public:
typedef T value_type;
typedef UserAllocator user_allocator;
typedef Mutex mutex;
BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
typedef value_type * pointer;
typedef const value_type * const_pointer;
typedef value_type & reference;
typedef const value_type & const_reference;
typedef typename pool<UserAllocator>::size_type size_type;
typedef typename pool<UserAllocator>::difference_type difference_type;
template <typename U>
struct rebind
{
typedef fast_pool_allocator<U, UserAllocator, Mutex, NextSize> other;
};
public:
fast_pool_allocator() { }
// default copy constructor
// default assignment operator
// not explicit, mimicking std::allocator [20.4.1]
template <typename U>
fast_pool_allocator(
const fast_pool_allocator<U, UserAllocator, Mutex, NextSize> &)
{ }
// default destructor
static pointer address(reference r)
{ return &r; }
static const_pointer address(const_reference s)
{ return &s; }
static size_type max_size()
{ return (std::numeric_limits<size_type>::max)(); }
void construct(const pointer ptr, const value_type & t)
{ new (ptr) T(t); }
void destroy(const pointer ptr)
{
ptr->~T();
(void) ptr; // avoid unused variable warning
}
bool operator==(const fast_pool_allocator &) const
{ return true; }
bool operator!=(const fast_pool_allocator &) const
{ return false; }
static pointer allocate(const size_type n)
{
const pointer ret = (n == 1) ?
static_cast<pointer>(
singleton_pool<fast_pool_allocator_tag, sizeof(T),
UserAllocator, Mutex, NextSize>::malloc() ) :
static_cast<pointer>(
singleton_pool<fast_pool_allocator_tag, sizeof(T),
UserAllocator, Mutex, NextSize>::ordered_malloc(n) );
if (ret == 0)
throw std::bad_alloc();
return ret;
}
static pointer allocate(const size_type n, const void * const)
{ return allocate(n); }
static pointer allocate()
{
const pointer ret = static_cast<pointer>(
singleton_pool<fast_pool_allocator_tag, sizeof(T),
UserAllocator, Mutex, NextSize>::malloc() );
if (ret == 0)
throw std::bad_alloc();
return ret;
}
static void deallocate(const pointer ptr, const size_type n)
{
#ifdef BOOST_NO_PROPER_STL_DEALLOCATE
if (ptr == 0 || n == 0)
return;
#endif
if (n == 1)
singleton_pool<fast_pool_allocator_tag, sizeof(T),
UserAllocator, Mutex, NextSize>::free(ptr);
else
singleton_pool<fast_pool_allocator_tag, sizeof(T),
UserAllocator, Mutex, NextSize>::free(ptr, n);
}
static void deallocate(const pointer ptr)
{
singleton_pool<fast_pool_allocator_tag, sizeof(T),
UserAllocator, Mutex, NextSize>::free(ptr);
}
};
} // namespace boost
#endif

View File

@@ -0,0 +1,73 @@
// Copyright (C) 2000, 2001 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_POOLFWD_HPP
#define BOOST_POOLFWD_HPP
#include <boost/config.hpp> // for workarounds
// std::size_t
#include <cstddef>
// boost::details::pool::default_mutex
#include <boost/pool/detail/mutex.hpp>
namespace boost {
//
// Location: <boost/pool/simple_segregated_storage.hpp>
//
template <typename SizeType = std::size_t>
class simple_segregated_storage;
//
// Location: <boost/pool/pool.hpp>
//
struct default_user_allocator_new_delete;
struct default_user_allocator_malloc_free;
template <typename UserAllocator = default_user_allocator_new_delete>
class pool;
//
// Location: <boost/pool/object_pool.hpp>
//
template <typename T, typename UserAllocator = default_user_allocator_new_delete>
class object_pool;
//
// Location: <boost/pool/singleton_pool.hpp>
//
template <typename Tag, unsigned RequestedSize,
typename UserAllocator = default_user_allocator_new_delete,
typename Mutex = details::pool::default_mutex,
unsigned NextSize = 32>
struct singleton_pool;
//
// Location: <boost/pool/pool_alloc.hpp>
//
struct pool_allocator_tag;
template <typename T,
typename UserAllocator = default_user_allocator_new_delete,
typename Mutex = details::pool::default_mutex,
unsigned NextSize = 32>
class pool_allocator;
struct fast_pool_allocator_tag;
template <typename T,
typename UserAllocator = default_user_allocator_new_delete,
typename Mutex = details::pool::default_mutex,
unsigned NextSize = 32>
class fast_pool_allocator;
} // namespace boost
#endif

View File

@@ -0,0 +1,265 @@
// Copyright (C) 2000, 2001 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_SIMPLE_SEGREGATED_STORAGE_HPP
#define BOOST_SIMPLE_SEGREGATED_STORAGE_HPP
// std::greater
#include <functional>
#include <boost/pool/poolfwd.hpp>
namespace boost {
template <typename SizeType>
class simple_segregated_storage
{
public:
typedef SizeType size_type;
private:
simple_segregated_storage(const simple_segregated_storage &);
void operator=(const simple_segregated_storage &);
// pre: (n > 0), (start != 0), (nextof(start) != 0)
// post: (start != 0)
static void * try_malloc_n(void * & start, size_type n,
size_type partition_size);
protected:
void * first;
// Traverses the free list referred to by "first",
// and returns the iterator previous to where
// "ptr" would go if it was in the free list.
// Returns 0 if "ptr" would go at the beginning
// of the free list (i.e., before "first")
void * find_prev(void * ptr);
// for the sake of code readability :)
static void * & nextof(void * const ptr)
{ return *(static_cast<void **>(ptr)); }
public:
// Post: empty()
simple_segregated_storage()
:first(0) { }
// pre: npartition_sz >= sizeof(void *)
// npartition_sz = sizeof(void *) * i, for some integer i
// nsz >= npartition_sz
// block is properly aligned for an array of object of
// size npartition_sz and array of void *
// The requirements above guarantee that any pointer to a chunk
// (which is a pointer to an element in an array of npartition_sz)
// may be cast to void **.
static void * segregate(void * block,
size_type nsz, size_type npartition_sz,
void * end = 0);
// Same preconditions as 'segregate'
// Post: !empty()
void add_block(void * const block,
const size_type nsz, const size_type npartition_sz)
{
// Segregate this block and merge its free list into the
// free list referred to by "first"
first = segregate(block, nsz, npartition_sz, first);
}
// Same preconditions as 'segregate'
// Post: !empty()
void add_ordered_block(void * const block,
const size_type nsz, const size_type npartition_sz)
{
// This (slower) version of add_block segregates the
// block and merges its free list into our free list
// in the proper order
// Find where "block" would go in the free list
void * const loc = find_prev(block);
// Place either at beginning or in middle/end
if (loc == 0)
add_block(block, nsz, npartition_sz);
else
nextof(loc) = segregate(block, nsz, npartition_sz, nextof(loc));
}
// default destructor
bool empty() const { return (first == 0); }
// pre: !empty()
void * malloc()
{
void * const ret = first;
// Increment the "first" pointer to point to the next chunk
first = nextof(first);
return ret;
}
// pre: chunk was previously returned from a malloc() referring to the
// same free list
// post: !empty()
void free(void * const chunk)
{
nextof(chunk) = first;
first = chunk;
}
// pre: chunk was previously returned from a malloc() referring to the
// same free list
// post: !empty()
void ordered_free(void * const chunk)
{
// This (slower) implementation of 'free' places the memory
// back in the list in its proper order.
// Find where "chunk" goes in the free list
void * const loc = find_prev(chunk);
// Place either at beginning or in middle/end
if (loc == 0)
free(chunk);
else
{
nextof(chunk) = nextof(loc);
nextof(loc) = chunk;
}
}
// Note: if you're allocating/deallocating n a lot, you should
// be using an ordered pool.
void * malloc_n(size_type n, size_type partition_size);
// pre: chunks was previously allocated from *this with the same
// values for n and partition_size
// post: !empty()
// Note: if you're allocating/deallocating n a lot, you should
// be using an ordered pool.
void free_n(void * const chunks, const size_type n,
const size_type partition_size)
{
add_block(chunks, n * partition_size, partition_size);
}
// pre: chunks was previously allocated from *this with the same
// values for n and partition_size
// post: !empty()
void ordered_free_n(void * const chunks, const size_type n,
const size_type partition_size)
{
add_ordered_block(chunks, n * partition_size, partition_size);
}
};
template <typename SizeType>
void * simple_segregated_storage<SizeType>::find_prev(void * const ptr)
{
// Handle border case
if (first == 0 || std::greater<void *>()(first, ptr))
return 0;
void * iter = first;
while (true)
{
// if we're about to hit the end or
// if we've found where "ptr" goes
if (nextof(iter) == 0 || std::greater<void *>()(nextof(iter), ptr))
return iter;
iter = nextof(iter);
}
}
template <typename SizeType>
void * simple_segregated_storage<SizeType>::segregate(
void * const block,
const size_type sz,
const size_type partition_sz,
void * const end)
{
// Get pointer to last valid chunk, preventing overflow on size calculations
// The division followed by the multiplication just makes sure that
// old == block + partition_sz * i, for some integer i, even if the
// block size (sz) is not a multiple of the partition size.
char * old = static_cast<char *>(block)
+ ((sz - partition_sz) / partition_sz) * partition_sz;
// Set it to point to the end
nextof(old) = end;
// Handle border case where sz == partition_sz (i.e., we're handling an array
// of 1 element)
if (old == block)
return block;
// Iterate backwards, building a singly-linked list of pointers
for (char * iter = old - partition_sz; iter != block;
old = iter, iter -= partition_sz)
nextof(iter) = old;
// Point the first pointer, too
nextof(block) = old;
return block;
}
// The following function attempts to find n contiguous chunks
// of size partition_size in the free list, starting at start.
// If it succeds, it returns the last chunk in that contiguous
// sequence, so that the sequence is known by [start, {retval}]
// If it fails, it does do either because it's at the end of the
// free list or hits a non-contiguous chunk. In either case,
// it will return 0, and set start to the last considered
// chunk. You are at the end of the free list if
// nextof(start) == 0. Otherwise, start points to the last
// chunk in the contiguous sequence, and nextof(start) points
// to the first chunk in the next contiguous sequence (assuming
// an ordered free list)
template <typename SizeType>
void * simple_segregated_storage<SizeType>::try_malloc_n(
void * & start, size_type n, const size_type partition_size)
{
void * iter = nextof(start);
while (--n != 0)
{
void * next = nextof(iter);
if (next != static_cast<char *>(iter) + partition_size)
{
// next == 0 (end-of-list) or non-contiguous chunk found
start = iter;
return 0;
}
iter = next;
}
return iter;
}
template <typename SizeType>
void * simple_segregated_storage<SizeType>::malloc_n(const size_type n,
const size_type partition_size)
{
void * start = &first;
void * iter;
do
{
if (nextof(start) == 0)
return 0;
iter = try_malloc_n(start, n, partition_size);
} while (iter == 0);
void * const ret = nextof(start);
nextof(start) = nextof(iter);
return ret;
}
} // namespace boost
#endif

View File

@@ -0,0 +1,119 @@
// Copyright (C) 2000, 2001 Stephen Cleary
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_SINGLETON_POOL_HPP
#define BOOST_SINGLETON_POOL_HPP
#include <boost/pool/poolfwd.hpp>
// boost::pool
#include <boost/pool/pool.hpp>
// boost::details::pool::singleton_default
#include <boost/pool/detail/singleton.hpp>
// boost::details::pool::guard
#include <boost/pool/detail/guard.hpp>
namespace boost {
//
// The singleton_pool class allows other pool interfaces for types of the same
// size to share the same pool
//
template <typename Tag, unsigned RequestedSize,
typename UserAllocator,
typename Mutex,
unsigned NextSize>
struct singleton_pool
{
public:
typedef Tag tag;
typedef Mutex mutex;
typedef UserAllocator user_allocator;
typedef typename pool<UserAllocator>::size_type size_type;
typedef typename pool<UserAllocator>::difference_type difference_type;
BOOST_STATIC_CONSTANT(unsigned, requested_size = RequestedSize);
BOOST_STATIC_CONSTANT(unsigned, next_size = NextSize);
private:
struct pool_type: Mutex
{
pool<UserAllocator> p;
pool_type():p(RequestedSize, NextSize) { }
};
typedef details::pool::singleton_default<pool_type> singleton;
singleton_pool();
public:
static void * malloc()
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
return p.p.malloc();
}
static void * ordered_malloc()
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
return p.p.ordered_malloc();
}
static void * ordered_malloc(const size_type n)
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
return p.p.ordered_malloc(n);
}
static bool is_from(void * const ptr)
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
return p.p.is_from(ptr);
}
static void free(void * const ptr)
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
p.p.free(ptr);
}
static void ordered_free(void * const ptr)
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
p.p.ordered_free(ptr);
}
static void free(void * const ptr, const size_type n)
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
p.p.free(ptr, n);
}
static void ordered_free(void * const ptr, const size_type n)
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
p.p.ordered_free(ptr, n);
}
static bool release_memory()
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
return p.p.release_memory();
}
static bool purge_memory()
{
pool_type & p = singleton::instance();
details::pool::guard<Mutex> g(p);
return p.p.purge_memory();
}
};
} // namespace boost
#endif