zoukankan
html css js c++ java
MemMan 1.0.0.2 Released!
/**/
/*
*************************************************
*
* MemMan 1.0.0.2
*
* 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
;
//
initialize balance factor with 0
}
//
we don't need a deconstructor for this class
FORCEINLINE
void
lock
()
{
locked
=
TRUE;
}
FORCEINLINE
void
unlock()
{
locked
=
FALSE;
}
FORCEINLINE MemoryHeader
*
insert( MemoryHeader
*
key )
{
MemoryHeader
*
root
=
this
;
bool
taller
=
true
;
create_child( key, root, taller );
return
root;
//
AVL may change the root, we return the new root here
}
FORCEINLINE
void
create_child( MemoryHeader
*
key, MemoryHeader
*
&
root,
bool
&
taller )
{
if
( key
->
priority
<
priority )
{
if
( lchild )
lchild
->
create_child( key, root, taller );
else
{
lchild
=
key;
lchild
->
parent
=
this
;
taller
=
true
;
}
if
( taller )
{
switch
( bfact )
{
case
1
:
left_balance( root );
taller
=
false
;
break
;
case
0
:
bfact
=
1
;
taller
=
true
;
break
;
case
-
1
:
bfact
=
0
;
taller
=
false
;
break
;
}
}
}
else
{
if
( rchild )
rchild
->
create_child( key, root, taller );
else
{
rchild
=
key;
rchild
->
parent
=
this
;
taller
=
true
;
}
if
( taller )
{
switch
( bfact )
{
case
1
:
bfact
=
0
;
taller
=
false
;
break
;
case
0
:
bfact
=
-
1
;
taller
=
true
;
break
;
case
-
1
:
right_balance( root );
taller
=
false
;
break
;
}
}
}
}
FORCEINLINE
void
left_rotate( MemoryHeader
*
&
root )
{
MemoryHeader
*
rc;
rc
=
rchild;
rchild
=
rc
->
lchild;
if
( rchild )
rchild
->
parent
=
this
;
rc
->
lchild
=
this
;
rc
->
parent
=
parent;
if
( parent )
{
if
( parent
->
lchild
==
this
)
parent
->
lchild
=
rc;
else
if
( parent
->
rchild
==
this
)
parent
->
rchild
=
rc;
}
else
{
root
=
rc;
}
parent
=
rc;
}
FORCEINLINE
void
right_rotate( MemoryHeader
*
&
root )
{
MemoryHeader
*
lc;
lc
=
lchild;
lchild
=
lc
->
rchild;
if
( lchild )
lchild
->
parent
=
this
;
lc
->
rchild
=
this
;
lc
->
parent
=
parent;
if
( parent )
{
if
( parent
->
lchild
==
this
)
parent
->
lchild
=
lc;
else
if
( parent
->
rchild
==
this
)
parent
->
rchild
=
lc;
}
else
{
root
=
lc;
}
parent
=
lc;
}
FORCEINLINE
void
left_balance( MemoryHeader
*
&
root )
{
MemoryHeader
*
lc,
*
rd;
lc
=
lchild;
switch
( lc
->
bfact )
{
case
1
:
bfact
=
lc
->
bfact
=
0
;
right_rotate( root );
break
;
case
0
:
rd
=
lc
->
rchild;
switch
( rd
->
bfact )
{
case
1
:
bfact
=
-
1
;
lc
->
bfact
=
0
;
break
;
case
0
:
bfact
=
lc
->
bfact
=
0
;
break
;
case
-
1
:
bfact
=
0
;
lc
->
bfact
=
1
;
break
;
}
rd
->
bfact
=
0
;
lchild
->
left_rotate( root );
right_rotate( root );
break
;
}
}
FORCEINLINE
void
right_balance( MemoryHeader
*
&
root )
{
MemoryHeader
*
rc,
*
ld;
rc
=
rchild;
switch
( rc
->
bfact )
{
case
1
:
bfact
=
rc
->
bfact
=
0
;
left_rotate( root );
break
;
case
0
:
ld
=
rc
->
lchild;
switch
( ld
->
bfact )
{
case
1
:
bfact
=
-
1
;
rc
->
bfact
=
0
;
break
;
case
0
:
bfact
=
rc
->
bfact
=
0
;
break
;
case
-
1
:
bfact
=
0
;
rc
->
bfact
=
1
;
break
;
}
ld
->
bfact
=
0
;
rchild
->
right_rotate( root );
left_rotate( root );
break
;
}
}
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
=
queue
->
insert( 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
=
aligned_queue
->
insert( 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__
查看全文
相关阅读:
Windows 2003,XP安装Windows Phone 7 狼人:
Android实例剖析笔记(六) 狼人:
Android实例剖析笔记(一) 狼人:
Android NDK带来什么 狼人:
Windows Phone 7常用资源大集合 狼人:
Android实例剖析笔记(七) 狼人:
JDK环境变量配置
jQuery去掉字符串起始和结尾的空格
结构型设计模式
主题:hibernate生成tree(基于注解方式)
原文地址:https://www.cnblogs.com/len3d/p/937404.html
最新文章
【VirtualBox打开出错】创建COM对象失败(XP3系统)
9patch制作.9.png图并应用到android实例中
Android修改文件和文件夹权限
[HBase] 停止集群报错,pid不存在
如何在android项目中引用project作为类库引用
用自由的软件
Linux下的crontab定时执行任务命令详解
git分支合并及冲突解决
Git 常用命令总结
git查看当前分支所属
热门文章
谷歌浏览器中kindeditor编译器字体不能为微软雅黑的问题?
Android随想 狼人:
Android实例剖析笔记(八) 狼人:
有效控制Android应用程序的耗电量 狼人:
Android实例剖析笔记(五) 狼人:
Android实例剖析笔记(二) 狼人:
QtCreator中常用快捷键总结 狼人:
Android实例剖析笔记(三) 狼人:
Android实例剖析笔记(四) 狼人:
Android Widget开发详解 狼人:
Copyright © 2011-2022 走看看