MNN/source/core/BufferAllocator.hpp

121 lines
3.4 KiB
C++
Raw Normal View History

2019-04-17 10:49:11 +08:00
//
// BufferAllocator.hpp
// MNN
//
// Created by MNN on 2018/08/20.
// Copyright © 2018, Alibaba Group Holding Limited
//
#ifndef BufferAllocator_hpp
#define BufferAllocator_hpp
#include <map>
#include <memory>
#include <vector>
#include "MNNMemoryUtils.h"
#include "NonCopyable.hpp"
namespace MNN {
/** memory utils wrapper. provides memory reusing with alignment ability. */
2019-12-27 22:16:57 +08:00
class MNN_PUBLIC BufferAllocator : public NonCopyable {
2019-04-17 10:49:11 +08:00
public:
2020-12-15 14:12:35 +08:00
class Allocator {
public:
Allocator() = default;
virtual ~ Allocator() = default;
virtual std::pair<void*, int> onAlloc(int size) = 0;
virtual void onRelease(std::pair<void*, int> ptr) = 0;
static std::shared_ptr<Allocator> createDefault();
static std::shared_ptr<Allocator> createRecurse(BufferAllocator* parent);
};
2019-04-17 10:49:11 +08:00
/**
* @brief init buffer allocator with pointer alignment.
* @param align given pointer alignment.
*/
2020-12-15 14:12:35 +08:00
BufferAllocator(std::shared_ptr<Allocator> parent, int align = MNN_MEMORY_ALIGN_DEFAULT) : mAllocator(parent), mAlign(align) {
2019-04-17 10:49:11 +08:00
// nothing to do
}
/**
* @brief deinit buffer allocator. frees all allocated memories.
*/
~BufferAllocator() {
release();
}
public:
/**
* @brief alloc CHUNK pointer with given size. if any reusable pointer matches size, reuse it.
* @param size given size.
* @param seperate if true, the memory can't be alloc from free pool
* @return allocated or used CHUNK pointer.
* @sa free
* @sa release
*/
2020-12-15 14:12:35 +08:00
std::pair<void*, int> alloc(int size, bool seperate = false);
2019-04-17 10:49:11 +08:00
/**
* @brief mark CHUNK pointer as reusable.
* @param pointer given CHUNK pointer.
* @return true if pointer is a CHUNK pointer, false otherwise.
* @sa release
*/
2020-12-15 14:12:35 +08:00
bool free(std::pair<void*, int> pointer);
2019-04-17 10:49:11 +08:00
/**
* @brief free all allocated memories.
* @sa allocSeparate
* @sa alloc
* if allRelease, clear all memory , otherwise delete freelist
2019-04-17 10:49:11 +08:00
*/
void release(bool allRelease = true);
2019-04-17 10:49:11 +08:00
/**
* @brief query total size allocated indeed.
* @return total size allocated indeed.
*/
size_t totalSize() const {
return mTotalSize;
}
/*
For multi thread case,
we must assume that the memory use by different thread don't conflict
begin barrier / end barrier means enter the alloc for multi-thread
begin group / end group means the memory allocated belong to one thread
different group must use different memory,
but the origin freelist can be used by every group
*/
void barrierBegin();
void barrierEnd();
void beginGroup();
void endGroup();
private:
class Node {
public:
~Node();
2020-12-15 14:12:35 +08:00
std::pair<void*, int> pointer;
std::shared_ptr<Node> parent = nullptr;
2020-11-05 16:41:56 +08:00
int32_t size;
int16_t useCount = 0;
2020-12-15 14:12:35 +08:00
Allocator* outside = nullptr;
2019-04-17 10:49:11 +08:00
};
typedef std::multimap<size_t, std::shared_ptr<Node>> FREELIST;
2019-04-17 10:49:11 +08:00
static void returnMemory(FREELIST* list, std::shared_ptr<Node> node, bool permitMerge = true);
2020-12-15 14:12:35 +08:00
std::pair<void*, int> getFromFreeList(FREELIST* list, int size, bool permiteSplit = true);
2019-04-17 10:49:11 +08:00
2020-12-15 14:12:35 +08:00
std::map<std::pair<void*, int>, std::shared_ptr<Node>> mUsedList;
2019-04-17 10:49:11 +08:00
FREELIST mFreeList;
size_t mTotalSize = 0;
2020-10-25 11:01:04 +08:00
FREELIST* mCurrentFreeList = nullptr;
2019-04-17 10:49:11 +08:00
std::vector<std::shared_ptr<FREELIST>> mGroups;
2020-12-15 14:12:35 +08:00
std::shared_ptr<Allocator> mAllocator;
int mAlign;
2019-04-17 10:49:11 +08:00
};
} // namespace MNN
#endif