zoukankan
html css js c++ java
MemMan 1.0.0.1 Released!
/**/
/*
*************************************************
*
* MemMan 1.0.0.1
*
* Copyright (C) 2007 - 2008 by Len3d
* All rights reserved.
*
************************************************
*/
#ifndef __MEM_MAN__
#define
__MEM_MAN__
#define
DEFAULT_MEMORY_ALIGN 16
//
default memory aligment set to this size
#define
ALIGN_DEF __declspec( align( DEFAULT_MEMORY_ALIGN ) )
typedef
int
(
*
FreeContentFunc)(
void
*
object
, UINT requested_size, UINT
&
ref_count );
//
can't be member function of a class
#pragma pack(push,
1
)
class
MemoryAllocator
{
//
memory allocator, takes charge of all system operations, also limits the usage of memory
private
:
typedef UINT MemoryHeaderBias;
//
biased value type of memory header
//
elements of the memory priority queue, keep track of all memory blocks
class
MemoryHeader
{
public
:
FORCEINLINE MemoryHeader( UINT prior,
void
*
obj, FreeContentFunc func, UINT al )
{
lchild
=
rchild
=
parent
=
NULL;
priority
=
prior;
object
=
obj;
free_func
=
func;
locked
=
TRUE;
//
we lock immediately after allocation
align
=
al;
ref_count
=
1
;
//
assume one block references this header at beginning
bias
=
sizeof
(MemoryHeader);
bfact
=
0
;
}
//
we don't need a deconstructor for this class
FORCEINLINE
void
lock
()
{
locked
=
TRUE;
}
FORCEINLINE
void
unlock()
{
locked
=
FALSE;
}
FORCEINLINE
void
create_child( MemoryHeader
*
key )
{
if
( key
->
priority
<
priority )
{
if
( lchild )
lchild
->
create_child( key );
else
{
lchild
=
key;
lchild
->
parent
=
this
;
}
}
else
{
if
( rchild )
rchild
->
create_child( key );
else
{
rchild
=
key;
rchild
->
parent
=
this
;
}
}
}
FORCEINLINE
bool
search_memory( UINT search_size,
int
search_align,
void
*
&
search_result,
void
*
obj, FreeContentFunc func )
{
if
( lchild
&&
lchild
->
search_memory( search_size, search_align, search_result, obj, func ) )
return
true
;
if
( align
==
search_align
&&
free_content( search_size ) )
{
search_result
=
get_memory();
object
=
obj;
//
update the attributes of the memory block
free_func
=
func;
return
true
;
}
if
( rchild
&&
rchild
->
search_memory( search_size, search_align, search_result, obj, func ) )
return
true
;
return
false
;
}
FORCEINLINE
void
*
get_memory()
//
the allocated memory block
{
return
((
char
*
)
this
+
sizeof
(MemoryHeader));
}
FORCEINLINE
void
dec_ref_count()
//
decrease the reference count
{
--
ref_count;
}
FORCEINLINE UINT get_ref_count()
//
the reference count
{
return
ref_count;
}
//
try to free some content of the object for requested size,
//
update the reference count and return the size of the freed memory
FORCEINLINE
int
free_content( UINT requested_size )
{
if
(
!
locked
&&
free_func
&&
object
)
return
free_func(
object
, requested_size, ref_count );
else
return
0
;
}
public
:
ALIGN_DEF
struct
{
//
48 Byte aligned including the header bias
MemoryHeader
*
lchild,
//
left child, right child and parent
*
rchild,
*
parent;
UINT priority;
//
priority for sorting the memory blocks
void
*
object
;
//
the object for which the memory was allocated
FreeContentFunc free_func;
//
function to free the content of the object for requested size,
//
memory blocks without this function will be restored to memory-mapped files.
int
locked;
//
this memory block was locked by a thread
int
bfact;
//
balance factor of the AVL tree
UINT align;
//
aligment of the allocated memory should match
UINT ref_count;
//
how many blocks reference this header
UINT pad;
//
padded to 48 Byte, no use
MemoryHeaderBias bias;
//
the header bias
}
;
}
;
public
:
MemoryAllocator( UINT max_size )
//
max allowed memory usage
{
allocated_size
=
0
;
available_size
=
max_size;
queue
=
NULL;
aligned_queue
=
NULL;
}
~
MemoryAllocator()
{
dealloc_header( queue );
dealloc_aligned_header( aligned_queue );
}
FORCEINLINE
void
*
alloc( UINT size, UINT priority,
void
*
object
, FreeContentFunc free_func )
{
if
( size
==
0
)
{
return
NULL;
}
else
if
( size
>
available_size )
//
searching has the complexity of O(N)
{
void
*
ptr
=
NULL;
if
( queue
&&
queue
->
search_memory( size,
0
, ptr,
object
, free_func ) )
return
ptr;
else
return
NULL;
//
the system has run out of memory
}
else
//
the complexity is O(logN)
{
allocated_size
+=
(
sizeof
(MemoryHeader)
+
size );
available_size
-=
(
sizeof
(MemoryHeader)
+
size );
MemoryHeader
*
elem;
//
allocate a block
elem
=
new
(sys_alloc(
sizeof
(MemoryHeader)
+
size )) MemoryHeader( priority,
object
, free_func,
0
);
if
( queue )
queue
->
create_child( elem );
//
insert the node
else
queue
=
elem;
//
be the root
return
elem
->
get_memory();
}
}
FORCEINLINE
void
*
aligned_alloc( UINT size, UINT priority,
void
*
object
, FreeContentFunc free_func,
UINT align
=
DEFAULT_MEMORY_ALIGN )
{
if
( size
==
0
)
{
return
NULL;
}
else
if
( size
>
available_size )
//
searching has the complexity of O(N)
{
void
*
ptr
=
NULL;
if
( aligned_queue
&&
aligned_queue
->
search_memory( size, align, ptr,
object
, free_func ) )
return
ptr;
else
return
NULL;
//
the system has run out of memory
}
else
//
the complexity is O(logN)
{
allocated_size
+=
(
sizeof
(MemoryHeader)
+
size );
available_size
-=
(
sizeof
(MemoryHeader)
+
size );
MemoryHeader
*
elem;
//
allocate an aligned block
elem
=
new
(sys_aligned_alloc(
sizeof
(MemoryHeader)
+
size, align )) MemoryHeader( priority,
object
, free_func, align );
if
( aligned_queue )
aligned_queue
->
create_child( elem );
//
insert the node
else
aligned_queue
=
elem;
//
be the root
return
elem
->
get_memory();
}
}
//
a lock must be used before the object being deallocated, the complexity is O(1)
FORCEINLINE
void
lock
(
void
*
ptr )
{
if
( ptr )
{
MemoryHeader
*
header
=
get_memory_header( ptr );
header
->
lock
();
}
}
FORCEINLINE
void
unlock(
void
*
ptr )
{
if
( ptr )
{
MemoryHeader
*
header
=
get_memory_header( ptr );
header
->
unlock();
}
}
//
deallocating has the complexity of O(logN)
FORCEINLINE
void
dealloc(
void
*
ptr, UINT size )
{
if
( ptr )
{
MemoryHeader
*
header,
*
node,
*
parent;
header
=
get_memory_header( ptr );
header
->
dec_ref_count();
if
( header
->
get_ref_count()
!=
0
)
//
still have objects reference this
return
;
parent
=
header
->
parent;
if
( header
->
lchild
&&
header
->
rchild )
//
has left child and right child
{
node
=
find_rightmost_child( header
->
lchild );
//
rebuild the links
if
( node
!=
header
->
lchild )
{
node
->
parent
->
rchild
=
node
->
lchild;
if
( node
->
lchild )
node
->
lchild
->
parent
=
node
->
parent;
node
->
lchild
=
header
->
lchild;
node
->
lchild
->
parent
=
node;
}
node
->
rchild
=
header
->
rchild;
node
->
rchild
->
parent
=
node;
node
->
parent
=
parent;
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
node;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
node;
}
else
//
it's the root
{
queue
=
node;
}
}
else
if
( header
->
lchild )
//
has only left child
{
//
rebuild the links
node
=
header
->
lchild;
node
->
parent
=
parent;
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
node;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
node;
}
else
//
it's the root
{
queue
=
node;
}
}
else
if
( header
->
rchild )
//
has only right child
{
//
rebuild the links
node
=
header
->
rchild;
node
->
parent
=
parent;
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
node;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
node;
}
else
//
it's the root
{
queue
=
node;
}
}
else
//
has no child
{
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
NULL;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
NULL;
}
else
//
it's the root, clear it
{
queue
=
NULL;
}
}
allocated_size
-=
(
sizeof
(MemoryHeader)
+
size );
available_size
+=
(
sizeof
(MemoryHeader)
+
size );
sys_dealloc( header );
//
deallocate the block
}
}
FORCEINLINE
void
aligned_dealloc(
void
*
ptr, UINT size )
{
if
( ptr )
{
MemoryHeader
*
header,
*
node,
*
parent;
header
=
get_memory_header( ptr );
header
->
dec_ref_count();
if
( header
->
get_ref_count()
!=
0
)
//
still have objects reference this
return
;
parent
=
header
->
parent;
if
( header
->
lchild
&&
header
->
rchild )
//
has left child and right child
{
node
=
find_rightmost_child( header
->
lchild );
//
rebuild the links
if
( node
!=
header
->
lchild )
{
node
->
parent
->
rchild
=
node
->
lchild;
if
( node
->
lchild )
node
->
lchild
->
parent
=
node
->
parent;
node
->
lchild
=
header
->
lchild;
node
->
lchild
->
parent
=
node;
}
node
->
rchild
=
header
->
rchild;
node
->
rchild
->
parent
=
node;
node
->
parent
=
parent;
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
node;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
node;
}
else
//
it's the root
{
aligned_queue
=
node;
}
}
else
if
( header
->
lchild )
//
has only left child
{
//
rebuild the links
node
=
header
->
lchild;
node
->
parent
=
parent;
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
node;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
node;
}
else
//
it's the root
{
aligned_queue
=
node;
}
}
else
if
( header
->
rchild )
//
has only right child
{
//
rebuild the links
node
=
header
->
rchild;
node
->
parent
=
parent;
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
node;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
node;
}
else
//
it's the root
{
aligned_queue
=
node;
}
}
else
//
has no child
{
if
( parent )
//
has parent
{
if
( parent
->
lchild
==
header )
parent
->
lchild
=
NULL;
else
if
( parent
->
rchild
==
header )
parent
->
rchild
=
NULL;
}
else
//
it's the root, clear it
{
aligned_queue
=
NULL;
}
}
allocated_size
-=
(
sizeof
(MemoryHeader)
+
size );
available_size
+=
(
sizeof
(MemoryHeader)
+
size );
sys_aligned_dealloc( header );
//
deallocate the block
}
}
private
:
//
help functions
FORCEINLINE
void
dealloc_header( MemoryHeader
*
node )
{
if
( node )
{
if
( node
->
lchild )
dealloc_header( node
->
lchild );
if
( node
->
rchild )
dealloc_header( node
->
rchild );
sys_dealloc( node );
}
}
FORCEINLINE
void
dealloc_aligned_header( MemoryHeader
*
node )
{
if
( node )
{
if
( node
->
lchild )
dealloc_aligned_header( node
->
lchild );
if
( node
->
rchild )
dealloc_aligned_header( node
->
rchild );
sys_aligned_dealloc( node );
}
}
FORCEINLINE MemoryHeader
*
find_rightmost_child( MemoryHeader
*
node )
{
while
( node
&&
node
->
rchild )
{
node
=
node
->
rchild;
}
return
node;
}
FORCEINLINE MemoryHeader
*
get_memory_header(
void
*
ptr )
{
//
get the biased value first
MemoryHeaderBias
*
pb
=
(MemoryHeaderBias
*
)((
char
*
) ptr
-
sizeof
(MemoryHeaderBias));
//
then get the header using the biased value
MemoryHeader
*
header
=
(MemoryHeader
*
)((
char
*
) ptr
-
(
*
pb));
return
header;
}
private
:
//
encapsulate system operations
FORCEINLINE
void
*
sys_alloc( UINT size )
{
return
malloc( size );
}
FORCEINLINE
void
*
sys_aligned_alloc( UINT size, UINT align )
{
return
_mm_malloc( size, align );
}
FORCEINLINE
void
sys_dealloc(
void
*
ptr )
{
free( ptr );
}
FORCEINLINE
void
sys_aligned_dealloc(
void
*
ptr )
{
_mm_free( ptr );
}
private
:
//
memory statistics
UINT allocated_size,
available_size;
//
implement priority queues to record all the allocations
MemoryHeader
*
queue;
MemoryHeader
*
aligned_queue;
}
;
#pragma pack(pop)
#endif
//
__MEM_MAN__
查看全文
相关阅读:
pycharm的集成vim
几款在线脑图制作工具
编辑器vim简介
常用服务器ftp、ssh
56. Merge Intervals
58. Length of Last Word
55. Jump Game
53. Maximum Subarray
52. N-Queens II
51. N-Queens
原文地址:https://www.cnblogs.com/len3d/p/936403.html
最新文章
python(26)- 面向对象补充Ⅱ
July 4th, Week 28th Monday, 2016
July 3rd, Week 28th Sunday, 2016
July 2nd, Week 27th Saturday, 2016
July 1st, Week 27th Friday, 2016
MTK 平台上如何给 camera 添加一种 preview size
mtk camera 移植步骤
Camera 涉及的文件70
unity用PUN进行信息交互模块
unity连接photon服务端模块
热门文章
android camera(四):camera 驱动 GT2005
android camera(三):camera V4L2 FIMC
android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)
android camera(一):camera模组CMM介绍
快速上手友盟推送前后端
H5混合开发二维码扫描以及调用本地摄像头
ip地址
网络通信概述
软件安装与卸载
编辑器sublime、终端运行python
Copyright © 2011-2022 走看看