1、Allocator类
声明:
class NCNN_EXPORT Allocator
{
public:
virtual ~Allocator();
virtual void* fastMalloc(size_t size) = 0;
virtual void fastFree(void* ptr) = 0;
};
Allocator类,内部包含三个虚函数:两个纯虚函数,一个虚析构函数。
纯虚函数:意味着Allocator是一个抽象类,不能对其实例化操作,只能通过其子类且非纯虚同名虚函数实现。若子类没有实现基类,则子类也是抽象类。
虚函数作用:基类指针指向子类的实例,从而调用子类的成员。
fastMalloc函数申请内存
fastFree函数释放内存
2、派生类PoolAllocator内存池
线程操作资源前中加锁
PoolAllocator类声明
class PoolAllocatorPrivate;
class NCNN_EXPORT PoolAllocator : public Allocator
{
public:
PoolAllocator();
~PoolAllocator();
// ratio range 0 ~ 1
// default cr = 0.75
void set_size_compare_ratio(float scr);
// release all budgets immediately
void clear();
//基类虚函数继承
virtual void* fastMalloc(size_t size);
virtual void fastFree(void* ptr);
private:
//构造函数:
PoolAllocator(const PoolAllocator&);
//赋值构造函数
PoolAllocator& operator=(const PoolAllocator&);
private:
//常指针
PoolAllocatorPrivate* const d;
};
PoolAllocatorPrivate类声明
class PoolAllocatorPrivate
{
public:
//互斥量-预算
Mutex budgets_lock;
//互斥量-支付
Mutex payouts_lock;
//尺寸占比
unsigned int size_compare_ratio; // 0~256
//预算
std::list<std::pair<size_t, void*> > budgets;
//支付
std::list<std::pair<size_t, void*> > payouts;
};
函数体实现:
PoolAllocator构造函数初始化
PoolAllocator::PoolAllocator()
: Allocator(), d(new PoolAllocatorPrivate)
{
d->size_compare_ratio = 192; // 0.75f * 256
}
PoolAllocator::PoolAllocator(const PoolAllocator&)
: d(0)
{
}
PoolAllocator& PoolAllocator::operator=(const PoolAllocator&)
{
return *this;
}
析构函数-指针释放
PoolAllocator::~PoolAllocator()
{
clear();
if (!d->payouts.empty())
{
NCNN_LOGE("FATAL ERROR! pool allocator destroyed too early");
#if NCNN_STDIO
std::list<std::pair<size_t, void*> >::iterator it = d->payouts.begin();
for (; it != d->payouts.end(); ++it)
{
void* ptr = it->second;
NCNN_LOGE("%p still in use", ptr);
}
#endif
}
delete d;
}
解锁
void PoolAllocator::clear()
{
d->budgets_lock.lock();
std::list<std::pair<size_t, void*> >::iterator it = d->budgets.begin();
for (; it != d->budgets.end(); ++it)
{
void* ptr = it->second;
ncnn::fastFree(ptr);
}
d->budgets.clear();
d->budgets_lock.unlock();
}
内存申请与释放
//快速申请内存
void* PoolAllocator::fastMalloc(size_t size)
{
//加锁
d->budgets_lock.lock();
// find free budget
std::list<std::pair<size_t, void*> >::iterator it = d->budgets.begin();
for (; it != d->budgets.end(); ++it)
{
size_t bs = it->first;
// size_compare_ratio ~ 100%
if (bs >= size && ((bs * d->size_compare_ratio) >> 8) <= size)
{
void* ptr = it->second;
d->budgets.erase(it);
d->budgets_lock.unlock();
d->payouts_lock.lock();
d->payouts.push_back(std::make_pair(bs, ptr));
d->payouts_lock.unlock();
return ptr;
}
}
d->budgets_lock.unlock();
// new
void* ptr = ncnn::fastMalloc(size);
d->payouts_lock.lock();
d->payouts.push_back(std::make_pair(size, ptr));
d->payouts_lock.unlock();
return ptr;
}
//快速释放内存
void PoolAllocator::fastFree(void* ptr)
{
d->payouts_lock.lock();
// return to budgets
std::list<std::pair<size_t, void*> >::iterator it = d->payouts.begin();
for (; it != d->payouts.end(); ++it)
{
if (it->second == ptr)
{
size_t size = it->first;
d->payouts.erase(it);
d->payouts_lock.unlock();
d->budgets_lock.lock();
d->budgets.push_back(std::make_pair(size, ptr));
d->budgets_lock.unlock();
return;
}
}
d->payouts_lock.unlock();
NCNN_LOGE("FATAL ERROR! pool allocator get wild %p", ptr);
ncnn::fastFree(ptr);
}
3、派生类UnlockedPoolAllocator
线程操作资源后解锁
class UnlockedPoolAllocatorPrivate;
class NCNN_EXPORT UnlockedPoolAllocator : public Allocator
{
public:
UnlockedPoolAllocator();
~UnlockedPoolAllocator();
// ratio range 0 ~ 1
// default cr = 0.75
void set_size_compare_ratio(float scr);
// release all budgets immediately
void clear();
virtual void* fastMalloc(size_t size);
virtual void fastFree(void* ptr);
private:
UnlockedPoolAllocator(const UnlockedPoolAllocator&);
UnlockedPoolAllocator& operator=(const UnlockedPoolAllocator&);
private:
UnlockedPoolAllocatorPrivate* const d;
};
UnlockedPoolAllocatorPrivate类声明
class UnlockedPoolAllocatorPrivate
{
public:
unsigned int size_compare_ratio; // 0~256
std::list<std::pair<size_t, void*> > budgets;
std::list<std::pair<size_t, void*> > payouts;
};