2002-12-14 22:43:18 +01:00
|
|
|
/*
|
|
|
|
* PROGRAM: Client/Server Common Code
|
|
|
|
* MODULE: alloc.h
|
|
|
|
* DESCRIPTION: Memory Pool Manager (based on B+ tree)
|
|
|
|
*
|
2003-09-08 22:23:46 +02:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
* You may obtain a copy of the Licence at
|
|
|
|
* http://www.gnu.org/licences/lgpl.html
|
|
|
|
*
|
|
|
|
* As a special exception this file can also be included in modules
|
|
|
|
* with other source code as long as that source code has been
|
|
|
|
* released under an Open Source Initiative certificed licence.
|
|
|
|
* More information about OSI certification can be found at:
|
|
|
|
* http://www.opensource.org
|
|
|
|
*
|
|
|
|
* This module 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 Lesser General Public Licence for more details.
|
|
|
|
*
|
|
|
|
* This module was created by members of the firebird development
|
|
|
|
* team. All individual contributions remain the Copyright (C) of
|
|
|
|
* those individuals and all rights are reserved. Contributors to
|
|
|
|
* this file are either listed below or can be obtained from a CVS
|
|
|
|
* history command.
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
2003-09-08 22:23:46 +02:00
|
|
|
* Created by: Nickolay Samofatov <skidder@bssys.com>
|
|
|
|
*
|
|
|
|
* STL allocator is based on one by Mike Nordell and John Bellardo
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
2003-09-08 22:23:46 +02:00
|
|
|
* Contributor(s):
|
|
|
|
*
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
2004-03-14 14:05:02 +01:00
|
|
|
* $Id: alloc.h,v 1.36 2004-03-14 13:05:02 alexpeshkoff Exp $
|
2002-12-14 22:43:18 +01:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
#ifndef CLASSES_ALLOC_H
|
|
|
|
#define CLASSES_ALLOC_H
|
2002-12-14 22:43:18 +01:00
|
|
|
|
2003-10-27 23:27:30 +01:00
|
|
|
#include <cstddef>
|
2003-11-03 03:05:14 +01:00
|
|
|
|
2002-12-14 22:43:18 +01:00
|
|
|
#include "../../include/fb_types.h"
|
2003-01-07 17:35:10 +01:00
|
|
|
#include "../../include/firebird.h"
|
|
|
|
#include "../jrd/common.h"
|
2003-01-09 20:47:46 +01:00
|
|
|
#include "../jrd/ib_stdio.h"
|
2002-12-14 22:43:18 +01:00
|
|
|
#include "tree.h"
|
2003-01-07 17:35:10 +01:00
|
|
|
#include "locks.h"
|
2003-02-20 07:36:40 +01:00
|
|
|
#ifdef HAVE_STDLIB_H
|
|
|
|
#include <stdlib.h> /* XPG: prototypes for malloc/free have to be in
|
|
|
|
stdlib.h (EKU) */
|
|
|
|
#endif
|
2003-08-11 13:21:21 +02:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#define THROW_BAD_ALLOC
|
|
|
|
#else
|
|
|
|
#define THROW_BAD_ALLOC throw (std::bad_alloc)
|
|
|
|
#endif
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
#define MAX_TREE_DEPTH 4
|
2003-01-07 17:35:10 +01:00
|
|
|
// Must be a power of 2
|
2003-10-11 01:56:57 +02:00
|
|
|
#define ALLOC_ALIGNMENT ALIGNMENT
|
2003-01-07 17:35:10 +01:00
|
|
|
|
|
|
|
#define MEM_ALIGN(X) FB_ALIGN(X,ALLOC_ALIGNMENT)
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
namespace Firebird {
|
|
|
|
|
|
|
|
struct MemoryBlock /* 16 bytes of block header is not too much I think */ {
|
2003-11-07 09:06:35 +01:00
|
|
|
class MemoryPool* pool;
|
2002-12-14 22:43:18 +01:00
|
|
|
bool used;
|
|
|
|
bool last;
|
|
|
|
SSHORT type;
|
|
|
|
size_t length; /* Includes only actual block size, header not included */
|
2003-08-26 12:58:06 +02:00
|
|
|
MemoryBlock *prev;
|
2003-01-07 17:35:10 +01:00
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
2003-11-07 09:06:35 +01:00
|
|
|
const char* file;
|
2002-12-14 22:43:18 +01:00
|
|
|
int line;
|
2003-01-07 17:35:10 +01:00
|
|
|
#endif
|
2002-12-14 22:43:18 +01:00
|
|
|
};
|
|
|
|
|
2002-12-16 19:33:54 +01:00
|
|
|
#define TYPE_POOL -1
|
|
|
|
#define TYPE_EXTENT -2
|
|
|
|
#define TYPE_LEAFPAGE -3
|
|
|
|
#define TYPE_TREEPAGE -4
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
// We store BlkInfo structures instead of BlkHeader pointers to get benefits from
|
|
|
|
// processor cache-hit optimizations
|
|
|
|
struct BlockInfo {
|
2003-11-07 09:06:35 +01:00
|
|
|
MemoryBlock* block;
|
2002-12-14 22:43:18 +01:00
|
|
|
size_t length;
|
2003-12-05 11:35:47 +01:00
|
|
|
static bool greaterThan(const BlockInfo& i1, const BlockInfo& i2) {
|
2002-12-14 22:43:18 +01:00
|
|
|
return (i1.length > i2.length) ||
|
|
|
|
(i1.length == i2.length && i1.block > i2.block);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MemoryExtent {
|
|
|
|
MemoryExtent *next;
|
2004-03-01 04:18:42 +01:00
|
|
|
size_t extent_size; // Includes extent header size
|
2002-12-14 22:43:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct PendingFreeBlock {
|
|
|
|
PendingFreeBlock *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Memory pool based on B+ tree of free memory blocks
|
2003-01-07 17:35:10 +01:00
|
|
|
|
|
|
|
// We are going to have two target architectures:
|
|
|
|
// 1. Multi-process server with customizable lock manager
|
|
|
|
// 2. Multi-threaded server with single process (SUPERSERVER)
|
2003-01-18 22:45:24 +01:00
|
|
|
//
|
|
|
|
// MemoryPool inheritance looks weird because we cannot use
|
|
|
|
// any pointers to functions in shared memory. VMT usage in
|
|
|
|
// MemoryPool and its descendants is prohibited
|
2003-02-04 21:18:36 +01:00
|
|
|
class MemoryPool {
|
2002-12-14 22:43:18 +01:00
|
|
|
private:
|
2003-01-09 20:47:46 +01:00
|
|
|
class InternalAllocator {
|
|
|
|
public:
|
2003-01-16 18:47:10 +01:00
|
|
|
void* allocate(size_t size) {
|
|
|
|
return ((MemoryPool*)this)->tree_alloc(size);
|
2003-01-10 22:37:18 +01:00
|
|
|
}
|
2003-01-16 18:47:10 +01:00
|
|
|
void deallocate(void* block) {
|
|
|
|
((MemoryPool*)this)->tree_free(block);
|
2003-01-10 22:37:18 +01:00
|
|
|
}
|
2003-01-09 20:47:46 +01:00
|
|
|
};
|
|
|
|
typedef BePlusTree<BlockInfo, BlockInfo, InternalAllocator,
|
2002-12-14 22:43:18 +01:00
|
|
|
DefaultKeyValue<BlockInfo>, BlockInfo> FreeBlocksTree;
|
|
|
|
FreeBlocksTree freeBlocks; // B+ tree ordered by (length,address)
|
|
|
|
MemoryExtent *extents; // Linked list of all memory extents
|
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
Vector<void*, 2> spareLeafs;
|
|
|
|
Vector<void*, MAX_TREE_DEPTH + 1> spareNodes;
|
2002-12-14 22:43:18 +01:00
|
|
|
bool needSpare;
|
|
|
|
PendingFreeBlock *pendingFree;
|
2004-03-01 04:18:42 +01:00
|
|
|
Mutex lock;
|
2003-01-18 22:45:24 +01:00
|
|
|
int extents_memory; // Sum of memory in allocated extents minus size of extents headers
|
|
|
|
int used_memory; // Size of used memory blocks including block headers
|
2003-01-10 13:27:57 +01:00
|
|
|
|
2003-01-18 19:02:12 +01:00
|
|
|
/* Returns NULL in case it cannot allocate requested chunk */
|
|
|
|
static void* external_alloc(size_t size);
|
|
|
|
|
2004-03-01 04:18:42 +01:00
|
|
|
static void external_free(void* blk, size_t size);
|
2003-01-18 19:02:12 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
void* tree_alloc(size_t size);
|
2003-01-10 13:27:57 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
void tree_free(void* block);
|
2003-01-10 13:27:57 +01:00
|
|
|
|
2003-01-03 17:03:30 +01:00
|
|
|
void updateSpare();
|
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
void addFreeBlock(MemoryBlock* blk);
|
2003-01-03 17:03:30 +01:00
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
void removeFreeBlock(MemoryBlock* blk);
|
2003-01-09 20:47:46 +01:00
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
void free_blk_extent(MemoryBlock* blk);
|
2003-01-18 22:45:24 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
// does all the stuff except locking and exceptions
|
|
|
|
void* internal_alloc(size_t size, SSHORT type = 0
|
2003-01-09 20:47:46 +01:00
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
2003-11-07 09:06:35 +01:00
|
|
|
, const char* file = NULL, int line = 0
|
2003-01-09 20:47:46 +01:00
|
|
|
#endif
|
|
|
|
);
|
2003-01-16 18:47:10 +01:00
|
|
|
protected:
|
2003-11-07 09:06:35 +01:00
|
|
|
int* cur_memory;
|
|
|
|
int* max_memory;
|
2003-01-16 18:47:10 +01:00
|
|
|
// Do not allow to create and destroy pool directly from outside
|
2003-11-07 09:06:35 +01:00
|
|
|
MemoryPool(void* first_extent, void* root_page, int* cur_mem = NULL, int* max_mem = NULL);
|
2003-01-09 20:47:46 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
// This should never be called
|
|
|
|
~MemoryPool() {
|
|
|
|
}
|
2003-01-07 17:35:10 +01:00
|
|
|
|
2003-01-18 22:45:24 +01:00
|
|
|
static MemoryPool* internal_create(size_t instance_size,
|
2003-11-07 09:06:35 +01:00
|
|
|
int* cur_mem = NULL, int* max_mem = NULL);
|
2003-01-16 18:47:10 +01:00
|
|
|
public:
|
2003-01-27 12:47:04 +01:00
|
|
|
static int process_max_memory;
|
|
|
|
static int process_current_memory;
|
|
|
|
|
2003-01-18 22:45:24 +01:00
|
|
|
// Move usage stats to another location
|
|
|
|
void moveStats(int *cur_mem, int *max_mem) {
|
|
|
|
*cur_mem = *cur_memory;
|
|
|
|
*max_mem = *max_memory;
|
|
|
|
cur_memory = cur_mem;
|
|
|
|
max_memory = max_mem;
|
|
|
|
}
|
2003-01-16 18:47:10 +01:00
|
|
|
static MemoryPool* createPool() {
|
|
|
|
return internal_create(sizeof(MemoryPool));
|
|
|
|
}
|
2002-12-14 22:43:18 +01:00
|
|
|
|
|
|
|
static void deletePool(MemoryPool* pool);
|
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
void* allocate(size_t size, SSHORT type = 0
|
2003-01-07 17:35:10 +01:00
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
2003-11-07 09:06:35 +01:00
|
|
|
, const char* file = NULL, int line = 0
|
2003-01-07 17:35:10 +01:00
|
|
|
#endif
|
|
|
|
);
|
2002-12-14 22:43:18 +01:00
|
|
|
|
2004-03-09 01:17:07 +01:00
|
|
|
void* allocate_nothrow(size_t size, SSHORT type = 0
|
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
|
|
, const char* file = NULL, int line = 0
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
void deallocate(void* block);
|
2002-12-16 19:33:54 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
bool verify_pool();
|
2002-12-14 22:43:18 +01:00
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
void print_contents(IB_FILE*, bool = false);
|
2003-01-09 20:47:46 +01:00
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
static void globalFree(void* block) {
|
2003-01-30 19:05:34 +01:00
|
|
|
if (block)
|
2004-02-20 07:43:27 +01:00
|
|
|
((MemoryBlock*)((char*)block - MEM_ALIGN(sizeof(MemoryBlock))))->pool->deallocate(block);
|
2003-01-07 17:35:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void* calloc(size_t size, SSHORT type = 0
|
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
2003-11-07 09:06:35 +01:00
|
|
|
, const char* file = NULL, int line = 0
|
2003-01-07 17:35:10 +01:00
|
|
|
#endif
|
|
|
|
) {
|
2003-01-16 18:47:10 +01:00
|
|
|
void* result = allocate(size, type
|
2003-01-07 17:35:10 +01:00
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
|
|
, file, line
|
|
|
|
#endif
|
|
|
|
);
|
2003-11-07 09:06:35 +01:00
|
|
|
memset(result, 0, size);
|
2003-01-09 20:47:46 +01:00
|
|
|
return result;
|
2003-01-07 17:35:10 +01:00
|
|
|
}
|
2003-01-10 13:27:57 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
/// Returns the type associated with the allocated memory.
|
|
|
|
static SSHORT blk_type(const void* mem) {
|
|
|
|
return ((MemoryBlock*)((char *)mem - MEM_ALIGN(sizeof(MemoryBlock))))->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the pool the memory was allocated from.
|
|
|
|
static MemoryPool* blk_pool(const void* mem) {
|
|
|
|
return ((MemoryBlock*)((char *)mem - MEM_ALIGN(sizeof(MemoryBlock))))->pool;
|
|
|
|
}
|
|
|
|
|
2003-01-10 13:27:57 +01:00
|
|
|
friend class InternalAllocator;
|
2002-12-14 22:43:18 +01:00
|
|
|
};
|
|
|
|
|
2003-01-07 17:35:10 +01:00
|
|
|
}; // namespace Firebird
|
|
|
|
|
|
|
|
#ifndef TESTING_ONLY
|
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
using Firebird::MemoryPool;
|
|
|
|
|
|
|
|
MemoryPool* getDefaultMemoryPool();
|
|
|
|
|
2003-11-03 03:05:14 +01:00
|
|
|
#if defined(__GNUC__) && !defined(MINGW)
|
2003-10-27 23:27:30 +01:00
|
|
|
// All this crappy code below under __GNUC__ conditional is to avoid replacing
|
|
|
|
// STL operator new as this replacement causes crashes if client library is
|
|
|
|
// loaded by host application using STL
|
|
|
|
|
|
|
|
// This is to prevent inclusion of <new> header
|
|
|
|
#ifdef __NEW__
|
|
|
|
#error "alloc.h must be included before <new>"
|
|
|
|
#endif
|
|
|
|
#define __NEW__
|
|
|
|
namespace std {
|
|
|
|
class bad_alloc : public exception {};
|
|
|
|
}
|
|
|
|
// Define operators as static inline to prevent replacement of STL versions
|
|
|
|
static inline void* operator new(size_t s) {
|
|
|
|
#if defined(DEV_BUILD)
|
|
|
|
// Do not complain here. It causes client tools to crash on Red Hat 8.0
|
|
|
|
// fprintf(stderr, "You MUST allocate all memory from a pool. Don't use the default global new().\n");
|
|
|
|
#endif // DEV_BUILD
|
|
|
|
// return getDefaultMemoryPool()->calloc(s, 0
|
|
|
|
return getDefaultMemoryPool()->allocate(s, 0
|
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
|
|
,__FILE__,__LINE__
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void* operator new[](size_t s) {
|
|
|
|
#if defined(DEV_BUILD)
|
|
|
|
// Do not complain here. It causes client tools to crash on Red Hat 8.0
|
|
|
|
// fprintf(stderr, "You MUST allocate all memory from a pool. Don't use the default global new[]().\n");
|
|
|
|
#endif // DEV_BUILD
|
2004-02-20 07:43:27 +01:00
|
|
|
// return getDefaultMemoryPool()->calloc(s, 0
|
2003-10-27 23:27:30 +01:00
|
|
|
return getDefaultMemoryPool()->allocate(s, 0
|
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
|
|
,__FILE__,__LINE__
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void operator delete(void* mem) throw() {
|
|
|
|
Firebird::MemoryPool::globalFree(mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void operator delete[](void* mem) throw() {
|
|
|
|
Firebird::MemoryPool::globalFree(mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default placement versions of operator new.
|
|
|
|
static inline void* operator new(size_t, void* __p) throw() { return __p; }
|
|
|
|
static inline void* operator new[](size_t, void* __p) throw() { return __p; }
|
|
|
|
|
|
|
|
#else
|
2003-01-07 17:35:10 +01:00
|
|
|
// Global versions of operator new() for compatibility with crappy libraries
|
2003-08-11 13:21:21 +02:00
|
|
|
void* operator new(size_t) THROW_BAD_ALLOC;
|
|
|
|
void* operator new[](size_t) THROW_BAD_ALLOC;
|
2003-01-07 17:35:10 +01:00
|
|
|
|
2003-10-27 23:27:30 +01:00
|
|
|
// We cannot use inline versions because we have to replace STL delete defined in <new> header
|
|
|
|
// One more performance pain we have to take because of STL usage :((
|
|
|
|
void operator delete(void* mem) throw();
|
|
|
|
|
|
|
|
void operator delete[](void* mem) throw();
|
|
|
|
#endif
|
|
|
|
|
2003-01-07 17:35:10 +01:00
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
2004-02-08 17:35:40 +01:00
|
|
|
static inline void* operator new(size_t s, Firebird::MemoryPool& pool, const char* file, int line) {
|
2003-02-25 02:11:29 +01:00
|
|
|
return pool.allocate(s, 0, file, line);
|
|
|
|
// return pool.calloc(s, 0, file, line);
|
|
|
|
}
|
2004-02-08 17:35:40 +01:00
|
|
|
static inline void* operator new[](size_t s, Firebird::MemoryPool& pool, const char* file, int line) {
|
2003-02-25 02:11:29 +01:00
|
|
|
return pool.allocate(s, 0, file, line);
|
|
|
|
// return pool.calloc(s, 0, file, line);
|
|
|
|
}
|
2003-01-07 17:35:10 +01:00
|
|
|
#define FB_NEW(pool) new(pool,__FILE__,__LINE__)
|
|
|
|
#define FB_NEW_RPT(pool,count) new(pool,count,__FILE__,__LINE__)
|
|
|
|
#else
|
2003-10-27 23:27:30 +01:00
|
|
|
static inline void* operator new(size_t s, Firebird::MemoryPool& pool) {
|
2003-02-25 02:11:29 +01:00
|
|
|
return pool.allocate(s);
|
|
|
|
// return pool.calloc(s);
|
|
|
|
}
|
2003-10-27 23:27:30 +01:00
|
|
|
static inline void* operator new[](size_t s, Firebird::MemoryPool& pool) {
|
2003-02-25 02:11:29 +01:00
|
|
|
return pool.allocate(s);
|
|
|
|
// return pool.calloc(s);
|
|
|
|
}
|
2003-01-07 17:35:10 +01:00
|
|
|
#define FB_NEW(pool) new(pool)
|
|
|
|
#define FB_NEW_RPT(pool,count) new(pool,count)
|
|
|
|
#endif
|
|
|
|
|
2003-02-16 01:20:30 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
This is the allocator template provided to be used with the STL.
|
|
|
|
Since the STL is the client of this class look to its documentation
|
|
|
|
to determine what the individual functions and typedefs do.
|
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
In order to use the allocator class you need to instanciate the
|
2003-01-16 18:47:10 +01:00
|
|
|
C++ container template with the allocator. For example if you
|
|
|
|
want to use a std::vector<int> the declaration would be:
|
|
|
|
|
|
|
|
std::vector<int, MemoryPool::allocator<int> >
|
|
|
|
|
|
|
|
The allocator, by default, allocates all memory from the process
|
|
|
|
wide pool FB_MemoryPool. Typically this is NOT the behavior you
|
|
|
|
want. Selection of the correct pool to allocate your memory from is
|
|
|
|
important. If you select a pool to far down in (a statement pool,
|
|
|
|
for example) you memory may be freed before you are done with it.
|
|
|
|
On the other hand if you always use the global pool you will
|
|
|
|
either leak memory or have to make sure you always delete the objects
|
|
|
|
you create.
|
|
|
|
|
|
|
|
If you decide to allocate the memory from a pool other than the global
|
|
|
|
pool you need to pass an allocator object to the constructor for
|
|
|
|
the STL object. For example:
|
|
|
|
|
|
|
|
std::vector<int, MemoryPool::allocator<int> > vec(MemoryPool::allocator<int>(poolRef, type));
|
|
|
|
The type is an optional parameter that defaults to 0.
|
|
|
|
**/
|
|
|
|
namespace Firebird
|
|
|
|
{
|
|
|
|
template <class T>
|
|
|
|
class allocator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef size_t size_type;
|
|
|
|
typedef ptrdiff_t difference_type;
|
|
|
|
typedef T* pointer;
|
|
|
|
typedef const T* const_pointer;
|
|
|
|
typedef T& reference;
|
|
|
|
typedef const T& const_reference;
|
|
|
|
typedef T value_type;
|
|
|
|
|
|
|
|
allocator(MemoryPool& p, SSHORT t = 0) : pool(&p), type(t) {}
|
2003-11-07 09:06:35 +01:00
|
|
|
allocator(MemoryPool* p = getDefaultMemoryPool(), SSHORT t = 0) : pool(p), type(t) {}
|
2003-01-16 18:47:10 +01:00
|
|
|
|
|
|
|
template <class DST>
|
|
|
|
allocator(const allocator<DST> &alloc)
|
2003-11-07 09:06:35 +01:00
|
|
|
: pool(alloc.getPool()), type(alloc.getType()) { }
|
2003-01-07 17:35:10 +01:00
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
2003-11-07 09:06:35 +01:00
|
|
|
pointer allocate(size_type s, const void* = 0)
|
2003-01-16 18:47:10 +01:00
|
|
|
{ return (pointer) pool->allocate(sizeof(T) * s, 0, __FILE__, __LINE__); }
|
2003-11-07 09:06:35 +01:00
|
|
|
char* _Charalloc(size_type n)
|
2003-01-16 18:47:10 +01:00
|
|
|
{ return (char*) pool->allocate(n, 0, __FILE__, __LINE__); }
|
|
|
|
#else
|
2003-11-07 09:06:35 +01:00
|
|
|
pointer allocate(size_type s, const void* = 0)
|
2003-01-16 18:47:10 +01:00
|
|
|
{ return (pointer) pool->allocate(sizeof(T) * s, 0); }
|
2003-11-07 09:06:35 +01:00
|
|
|
char* _Charalloc(size_type n)
|
2003-01-16 18:47:10 +01:00
|
|
|
{ return (char*) pool->allocate(n, 0); }
|
2003-01-07 17:35:10 +01:00
|
|
|
#endif
|
2003-01-16 18:47:10 +01:00
|
|
|
/*#ifdef DEBUG_GDS_ALLOC
|
|
|
|
pointer allocate(size_type s, const void * = 0)
|
|
|
|
{ return (pointer) pool->calloc(sizeof(T) * s, 0, __FILE__, __LINE__); }
|
|
|
|
char *_Charalloc(size_type n)
|
|
|
|
{ return (char*) pool->calloc(n, 0, __FILE__, __LINE__); }
|
|
|
|
#else
|
|
|
|
pointer allocate(size_type s, const void * = 0)
|
|
|
|
{ return (pointer) pool->calloc(sizeof(T) * s, 0); }
|
|
|
|
char *_Charalloc(size_type n)
|
|
|
|
{ return (char*) pool->calloc(n, 0); }
|
|
|
|
#endif*/
|
|
|
|
|
|
|
|
void deallocate(pointer p, size_type s) { pool->deallocate(p); }
|
|
|
|
void deallocate(void* p, size_type s) { pool->deallocate(p); }
|
|
|
|
void construct(pointer p, const T& v) { new(p) T(v); }
|
|
|
|
void destroy(pointer p) { p->~T(); }
|
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
size_type max_size() const { return (size_type) - 1 / sizeof(T); }
|
2003-01-16 18:47:10 +01:00
|
|
|
|
|
|
|
pointer address(reference X) const { return &X; }
|
|
|
|
const_pointer address(const_reference X) const { return &X; }
|
|
|
|
|
|
|
|
template <class _Tp1> struct rebind {
|
|
|
|
typedef Firebird::allocator<_Tp1> other;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool operator==(const allocator<T>& rhs) const
|
|
|
|
{
|
|
|
|
return pool == rhs.pool && type == rhs.type;
|
|
|
|
}
|
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
MemoryPool* getPool() const { return pool; }
|
2003-01-16 18:47:10 +01:00
|
|
|
SSHORT getType() const { return type; }
|
|
|
|
|
|
|
|
private:
|
2003-11-07 09:06:35 +01:00
|
|
|
MemoryPool* pool;
|
2003-01-16 18:47:10 +01:00
|
|
|
SSHORT type;
|
|
|
|
};
|
|
|
|
|
2004-03-14 14:05:02 +01:00
|
|
|
class PermanentStorage {
|
|
|
|
private:
|
|
|
|
MemoryPool& pool;
|
|
|
|
protected:
|
|
|
|
explicit PermanentStorage(MemoryPool& p) : pool(p) { }
|
|
|
|
MemoryPool& getPool() const { return pool; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class AutoStorage : public PermanentStorage {
|
|
|
|
public:
|
|
|
|
static MemoryPool& getAutoMemoryPool() { return *getDefaultMemoryPool(); }
|
|
|
|
protected:
|
|
|
|
AutoStorage() : PermanentStorage(getAutoMemoryPool()) { }
|
|
|
|
explicit AutoStorage(MemoryPool& p) : PermanentStorage(p) { }
|
|
|
|
};
|
|
|
|
|
2003-01-16 18:47:10 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /*TESTING_ONLY*/
|
2003-01-07 17:35:10 +01:00
|
|
|
|
2004-03-07 08:58:55 +01:00
|
|
|
#endif // CLASSES_ALLOC_H
|
2003-11-07 09:06:35 +01:00
|
|
|
|