/usr/include/dar/on_pool.hpp is in libdar-dev 2.5.3-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2052 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// to contact the author : http://dar.linux.free.fr/email.html
/*********************************************************************/
/// \file on_pool.hpp
/// \brief this is the base class of object that can be allocated on a memory pool
/// \ingroup Private
#ifndef ON_POOL_HPP
#define ON_POOL_HPP
#include "/usr/include/dar/libdar_my_config.h"
#include <vector>
#include <new>
#include "/usr/include/dar/integers.hpp"
#include "/usr/include/dar/memory_pool.hpp"
#include "/usr/include/dar/mem_allocator.hpp"
#include "/usr/include/dar/cygwin_adapt.hpp"
namespace libdar
{
/// \addtogroup Private
/// @{
/// class on_pool is the ancestors of all class that are able to be allocated on a memory pool
///
/// \note: new and new[] operators using memory pool never throw an exception upon allocation failure
/// but rather return nullptr pointer. This is the way it was working before g++03 and g++11
class on_pool
{
public:
#ifdef LIBDAR_SPECIAL_ALLOC
/// constructor
///
/// \note If an object has been created by new (not new[], temporary, or local variable)
/// the get_pool() method can return the pool used for allocation, else it returns nullptr.
/// The consequence is that objects dynamically created within an array (new []) cannot know
/// the whether they have been allocated using a memory pool or not
on_pool() { dynamic_init(); };
/// copy constructor
///
/// \note the default copy constructor is not adequate as it would copy the value of dynamic
/// of the source object whatever is the way the new object is created (dynamically allocated or not)
on_pool(const on_pool & ref) { dynamic_init(); };
/// the assignment operator
///
/// \note the assignement operator must not modify the field "dynamic" so we must not use
/// the default operator
const on_pool & operator = (const on_pool & ref) { return *this; };
/// virtual destructor as this class will have inherited classes
virtual ~on_pool() throw(Ebug) {};
#endif
/// the usual new operator is wrapped to allow proper delete operation later on (throws std::bad_alloc upon allocation failure)
///
/// \note memory allocation done this way does not use the default C++ new[] operator, which may be slower than using memory pool
void *operator new(size_t n_byte) { void *ret = alloc(n_byte, nullptr); if(ret == nullptr) throw std::bad_alloc(); return ret; };
/// the usual new operator is wrapped to allow proper delete operation later on (does not throw exception upon allocation failure)
///
/// \note memory allocation done this way does not use the default C++ new[] operator, which may be slower than using memory pool
void *operator new(size_t n_byte, const std::nothrow_t & nothrow_value) { return alloc(n_byte, nullptr); };
/// the usual new[] operator is wrapped to allow proper delete[] operation later on (throws std::bad_alloc upon allocation failure)
///
/// \note memory allocation done this way does not use the default C++ new[] operator, which may be slower than using memory pool
void *operator new[](size_t n_byte) { void *ret = alloc(n_byte, nullptr); if(ret == nullptr) throw std::bad_alloc(); return ret; };
/// the usual new[] operator is wrapped to allow proper delete[] operation later on (does not throw exception upon allocation failure)
///
/// \note memory allocation done this way does not use the default C++ new[] operator, which may be slower than using memory pool
void *operator new[](size_t n_byte, const std::nothrow_t & nothrow_value) { return alloc(n_byte, nullptr); };
/// this operator allocates a single object on a memory pool
///
/// \note usage is: type *ptr = new (pool_obj) type(initial,values)
/// \note such object has to be delete normally no need to call the destructor manually
void *operator new(size_t n_byte, memory_pool *p) { return alloc(n_byte, p); };
/// this operator allocates an array of objects on a memory pool
///
/// \note usage is: type *ptr = new (pool_obj) type(initial,values)
/// \note such object has to be delete normally no need to call the destructor manually
void *operator new[] (size_t n_byte, memory_pool *p) { return alloc(n_byte, p); };
/// this operator is called by the compiler if an exception is throw from the constructor of the allocated object
void operator delete(void *ptr, memory_pool *p) { dealloc(ptr); };
/// this operator is called by the compiler if an exception is throw from the constructor of the allocated objects
void operator delete[](void *ptr, memory_pool *p) { dealloc(ptr); };
/// this is the usual delete operator, modified to handle allocated objects allocated on a memory pool or not
void operator delete(void *ptr) { dealloc(ptr); };
/// this is the usual delete[] operator, modified to handle allocated objects allocated on a memory pool or not
void operator delete[](void *ptr) { dealloc(ptr); };
protected:
/// get the pool used to allocate "this"
///
/// \return the address of the memory pool that has been used to allocate the object
/// \note if the object has not been allocated using a memory pool nullptr is returned
/// \note if the object has not been dynamically allocated, that's to say is a local variable
/// or a temporary object, get_pool() must not be called as it will return unpredictable
/// result and could most probably crash the application if the returned data is used
#ifdef LIBDAR_SPECIAL_ALLOC
memory_pool *get_pool() const { return dynamic ? (((pool_ptr *)this) - 1)->reserve : nullptr; };
#else
memory_pool *get_pool() const { return nullptr; };
#endif
template <class T> void meta_new(T * & ptr, size_t num)
{
#ifdef LIBDAR_SPECIAL_ALLOC
size_t byte = num * sizeof(T);
if(get_pool() != nullptr)
ptr = (T *)get_pool()->alloc(byte);
else
ptr = (T *)new (std::nothrow) char [byte];
#else
ptr = new (std::nothrow) T[num];
#endif
}
template <class T> void meta_delete(T * ptr)
{
#ifdef LIBDAR_SPECIAL_ALLOC
if(get_pool() != nullptr)
get_pool()->release(ptr);
else
delete [] (char *)(ptr);
#else
delete [] ptr;
#endif
}
private:
#ifdef LIBDAR_SPECIAL_ALLOC
/// this data structure is placed at the beginning of any allocated block
///
/// \note thanks to this structure, it is possible to know which memory pool has to be
/// informed of the memory release in order for the memory block to be recyclable
union pool_ptr
{
memory_pool *reserve; //< this is to be able to pass the pool object to the constructor if it requires dynamic memory allocation
U_I alignment__i; //< to properly align the allocated memory block that follows
U_32 alignment_32; //< to properly align the allocated memory block that follows
U_64 alignment_64; //< to properly align the allocated memory block that follows
};
// this field is necessary to make distinction between object on the heap that have a pool_ptr header from those
// created as local or temporary variable (on the stack).
bool dynamic;
/// used from constructors to setup field "dynamic"
void dynamic_init() const { const_cast<on_pool *>(this)->dynamic = (alloc_not_constructed == this); alloc_not_constructed = nullptr; };
#endif
/// does the whole magic of memory allocation with and without memory_pool
///
/// \param[in] size is the size of the requested block of memory to allocate
/// \param[in] is the address of the pool to request the memory block to, nullptr if default memory allocation shall be used
/// \return the address of the allocated memory block is returned, nullptr is returned upon memory allocation failure
static void *alloc(size_t size, memory_pool *p);
/// does the whole magic of memory release with and without memory_pool
///
/// \param[in] ptr is the address of the memory block to release
/// \note may throw exceptions if the given address has never been allocated or is nullptr
static void dealloc(void *ptr);
#ifdef LIBDAR_SPECIAL_ALLOC
#ifdef CYGWIN_BUILD
static on_pool *alloc_not_constructed;
// under cygwin the thread_local directive does not work but
// as we build only command-line tools that are single threaded
// program, it does not hurt using global static field here
// well, as soon as another application than dar/dar_xform/...
// relies on a cygwin build of libdar, this trick should be changed
#else
thread_local static on_pool * alloc_not_constructed;
#endif
#endif
};
/// @}
} // end of namespace
#endif
|