mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-04-20 09:07:44 +03:00
145 lines
3.8 KiB
C++
145 lines
3.8 KiB
C++
/* Copyright (C) 2014 InfiniDB, Inc.
|
|
|
|
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; version 2 of
|
|
the License.
|
|
|
|
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., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
/******************************************************************************************
|
|
* $Id$
|
|
*
|
|
******************************************************************************************/
|
|
|
|
/* This allocator is for frequent small allocations that all get deallocated at once.
|
|
It allocates large blocks of memory from the system and distributes 'allocsize'
|
|
units to the caller. When the large allocation is used up, it will allocate
|
|
more unless the 'tmpspace' flag is set. If it is, it will reuse the memory it
|
|
already allocated. This is useful for short-lived vars that are guaranteed to be
|
|
out of scope by the time the allocator wraps around.
|
|
|
|
TODO: make it STL and boost compliant...
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <vector>
|
|
#include <limits>
|
|
#include <unistd.h>
|
|
#include <atomic>
|
|
#include "spinlock.h"
|
|
|
|
#define EXPORT
|
|
|
|
namespace utils
|
|
{
|
|
class FixedAllocator
|
|
{
|
|
public:
|
|
EXPORT static const unsigned long DEFAULT_NUM_ELEMENTS = (4096 * 4); // should be a multiple of pagesize
|
|
|
|
EXPORT FixedAllocator()
|
|
: capacityRemaining(0)
|
|
, elementCount(DEFAULT_NUM_ELEMENTS)
|
|
, elementSize(0)
|
|
, currentlyStored(0)
|
|
, tmpSpace(false)
|
|
, nextAlloc(0)
|
|
, useLock(false)
|
|
, lock(false)
|
|
{
|
|
}
|
|
EXPORT explicit FixedAllocator(unsigned long allocSize, bool isTmpSpace = false,
|
|
unsigned long numElements = DEFAULT_NUM_ELEMENTS)
|
|
: capacityRemaining(0)
|
|
, elementCount(numElements)
|
|
, elementSize(allocSize)
|
|
, currentlyStored(0)
|
|
, tmpSpace(isTmpSpace)
|
|
, nextAlloc(0)
|
|
, useLock(false)
|
|
, lock(false)
|
|
{
|
|
}
|
|
EXPORT FixedAllocator(const FixedAllocator&);
|
|
EXPORT FixedAllocator& operator=(const FixedAllocator&);
|
|
virtual ~FixedAllocator()
|
|
{
|
|
}
|
|
|
|
EXPORT void* allocate();
|
|
EXPORT void* allocate(
|
|
uint32_t len); // a hack to make it work more like a pool allocator (use PoolAllocator instead)
|
|
EXPORT void truncateBy(uint32_t amt); // returns a portion of mem just allocated; use with caution
|
|
void deallocate()
|
|
{
|
|
} // does nothing
|
|
EXPORT void deallocateAll(); // drops all memory in use
|
|
EXPORT uint64_t getMemUsage() const;
|
|
void setUseLock(bool);
|
|
void setAllocSize(uint);
|
|
|
|
private:
|
|
void newBlock();
|
|
|
|
std::vector<std::shared_ptr<uint8_t[]>> mem;
|
|
unsigned long capacityRemaining;
|
|
uint64_t elementCount;
|
|
unsigned long elementSize;
|
|
uint64_t currentlyStored;
|
|
bool tmpSpace;
|
|
uint8_t* nextAlloc;
|
|
bool useLock;
|
|
std::atomic<bool> lock;
|
|
};
|
|
|
|
inline void* FixedAllocator::allocate()
|
|
{
|
|
void* ret;
|
|
|
|
if (useLock)
|
|
getSpinlock(lock);
|
|
if (capacityRemaining < elementSize)
|
|
newBlock();
|
|
|
|
ret = nextAlloc;
|
|
nextAlloc += elementSize;
|
|
capacityRemaining -= elementSize;
|
|
currentlyStored += elementSize;
|
|
if (useLock)
|
|
releaseSpinlock(lock);
|
|
return ret;
|
|
}
|
|
|
|
inline void* FixedAllocator::allocate(uint32_t len)
|
|
{
|
|
void* ret;
|
|
|
|
if (useLock)
|
|
getSpinlock(lock);
|
|
if (capacityRemaining < len)
|
|
newBlock();
|
|
|
|
ret = nextAlloc;
|
|
nextAlloc += len;
|
|
capacityRemaining -= len;
|
|
currentlyStored += len;
|
|
if (useLock)
|
|
releaseSpinlock(lock);
|
|
return ret;
|
|
}
|
|
|
|
#undef EXPORT
|
|
} // namespace utils
|