簡介:
在Android4.4中,在hwui将以前的繪制指令由原來的枚舉類型,全部以類的形式呈現(一是為了便于擴充,二是由于加入延時渲染清單,不得不用類來實作),抽象類為DisplayListOp,在該類中重載了new的方法,即用了new placement的方式,統一配置設定記憶體,而不是每個操作自己配置設定,即用了LinearAllocator來管理每個操作需要申請的記憶體,這樣能夠提升申請記憶體的性能,同時能夠便于統一管理。
class DisplayListOp {
public:
// These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
// standard new() intentionally not implemented, and delete/deconstructor should never be used.
virtual ~DisplayListOp() { CRASH(); }
static void operator delete(void* ptr) { CRASH(); }
/** static void* operator new(size_t size); PURPOSELY OMITTED **/
static void* operator new(size_t size, LinearAllocator& allocator) {
return allocator.alloc(size);
}
實作:
LinearAllocator主要用于多個對象需要重複申請,同時這些對象的生命周期都類似的情況。
實作原理即需要使用該記憶體配置設定的對象,需要使用new placement的方式,不需要自己申請記憶體,申請記憶體統一使用LinearAllocator來申請。在LinearAllocator内部配置設定了主要通過頁的方式來申請記憶體,每頁4kb,每頁之間通過單連結清單的方式來組織。
1. 當需要申請記憶體時,判斷目前頁是否滿足需要記憶體大小的申請。
2. 如果滿足,則直接傳回目前記憶體,将指針遊标指向下一個記憶體開始。
3. 如果不滿足,則需要重新申請一頁大小的記憶體,将記憶體除了Page結構大小外的位址開始傳回。
4. 如果需要,也可以在每個申請的記憶體之間加入一定的标記,用于記憶體的管理。
#pragma once
class LinearAllocator
{
public:
LinearAllocator();
~LinearAllocator();
void* alloc(size_t size);
private:
class Page;
Page* newPage(size_t size);
Page* mHeadPage;
Page* mCurrentPage;
void* mNext;
size_t mMemoryCount;
};
#include <stdio.h>
#include <stdlib.h>
#include "LinearAllocator.h"
class LinearAllocator::Page
{
public:
Page()
{
mNextPage = NULL;
}
~Page()
{
}
void* operator new(size_t size, void* buf)
{
return buf;
}
//this is the memory begin, add the page size is 4, so the next is the real memory
void* start()
{
return (void*)((size_t)this + sizeof(Page));
}
void* end(size_t size)
{
return (char*)start() + size;
}
Page* mNextPage;
};
//page size is 4kb
const int ONE_PAGE_SIZE = 4096;
#define ALIGN_INT(x) (x + sizeof(int) -1) &~(sizeof(int) -1)
LinearAllocator::LinearAllocator()
{
mHeadPage = mCurrentPage = NULL;
mNext = NULL;
mMemoryCount = 0;
}
//delete all the memory
LinearAllocator::~LinearAllocator()
{
Page* p = mHeadPage;
while(p)
{
Page* pNext = p->mNextPage;
p->~Page();
free(p);
p = pNext;
}
}
LinearAllocator::Page* LinearAllocator::newPage(size_t size)
{
size_t allocSize = ALIGN_INT(sizeof(Page)+ size);
mMemoryCount += allocSize;
void* p = malloc(allocSize);
return new(p) Page();
}
void* LinearAllocator::alloc(size_t size)
{
size = ALIGN_INT(size);
if (NULL == mHeadPage)
{
mHeadPage = mCurrentPage = newPage(ONE_PAGE_SIZE);
mNext = mCurrentPage->start();
}
else if ((char*)mNext + size > mCurrentPage->end(ONE_PAGE_SIZE))
{
Page* p = newPage(ONE_PAGE_SIZE);
mCurrentPage->mNextPage = p;
mCurrentPage = p;
mNext = mCurrentPage->start();
}
void* ptr = mNext;
mNext = (char*)mNext + size;
return ptr;
}
使用方式:
class AllocTest
{
public:
AllocTest()
{
mCount ++;
a = mCount;
b = a+1;
c = b+1;
}
void* operator new (size_t size, LinearAllocator& linearAlloc)
{
return linearAlloc.alloc(size);
}
void dump()
{
cout<<"a = "<<a<<" b="<<b<<" c="<<c<<endl;
}
int a;
int b;
int c;
static int mCount;
};
int AllocTest::mCount = 0;
class LinearAllocTest
{
public:
LinearAllocTest()
{
AllocTest* test1 = new(mLinearAlloc)AllocTest();
AllocTest* test2 = new(mLinearAlloc)AllocTest();
AllocTest* test3 = new(mLinearAlloc)AllocTest();
AllocTest* test4 = new(mLinearAlloc)AllocTest();
test1->dump();
test2->dump
}
~LinearAllocTest()
{
}
private:
LinearAllocator mLinearAlloc;
};
同時也可以參考Android源碼:
system/core/include/utils/LinearAllocator.h