分配器
描述
ACE_Allocator
ACE中的分配器类的接口类。这些类使用继承和动态绑定来提供灵活性。
ACE_Static_Allocator
该分配器管理固定大小的内存。每当收到分配内存的请求时,它就移动内部指针、以返回内存chunk(“大块”)。它还假定内存一旦被分配,就再也不会被释放。
ACE_Cached_Allocator
该分配器预先分配内存池,其中含有特定数目和大小的内存chunk。这些chunk在内部空闲表(free list)中进行维护,并在收到内存请求(malloc())时被返回。当应用调用free()时,chunk被归还到内部空闲表、而不是OS中。
ACE_New_Allocator
为C++ new和delete操作符提供包装的分配器,也就是,它在内部使用new和delete操作符,以满足动态内存请求。
#include
"
ace/Malloc.h
"
//
A chunk of size 1K is created. In our case we decided to use a simple array
//
as the type for the chunk. Instead of this we could use any struct or class
//
that we think is appropriate.
typedef
char
MEMORY_BLOCK[
1024
];
//
Create an ACE_Cached_Allocator which is passed in the type of the
//
“chunk” that it must pre-allocate and assign on the free list.
//
Since the Cached_Allocator is a template class we can pretty much
//
pass it ANY type we think is appropriate to be a memory block.
typedef ACE_Cached_Allocator
<
MEMORY_BLOCK,ACE_SYNCH_MUTEX
>
Allocator;
class
MessageManager
{
public
:
//
The constructor is passed the number of chunks that the allocator
//
should pre-allocate and maintain on its free list.
MessageManager(
int
n_blocks):
allocator_(n_blocks),message_count_(
0
)
{
mesg_array_
=
new
char
*
[n_blocks];
}
//
Allocate memory for a message using the Allocator. Remember the message
//
in an array and then increase the message count of valid messages
//
on the message array.
void
allocate_msg(
const
char
*
msg)
{
mesg_array_[message_count_]
=
(
char
*
)allocator_.malloc(ACE_OS::strlen(msg)
+
1
);
ACE_OS::strcpy(mesg_array_[message_count_],msg);
message_count_
++
;
}
//
Free all the memory that was allocated. This will cause the chunks
//
to be returned to the allocator’s internal free list
//
and NOT to the OS.
void
free_all_msg()
{
for
(
int
i
=
0
;i
<
message_count_;i
++
)
allocator_.free(mesg_array_[i]);
message_count_
=
0
;
}
//
Just show all the currently allocated messages in the message array.
void
display_all_msg()
{
for
(
int
i
=
0
;i
<
message_count_;i
++
)
ACE_OS::printf(
"
%s\n
"
,mesg_array_[i]);
}
private
:
char
**
mesg_array_;
Allocator allocator_;
int
message_count_;
}
;
int
main(
int
argc,
char
*
argv[])
{
char
message[
512
]
=
{
0
}
;
if
(argc
<
2
)
{
ACE_DEBUG((LM_DEBUG,
"
Usage: %s <Number of blocks>\n
"
, argv[
0
]));
exit(
1
);
}
int
n_blocks
=
ACE_OS::atoi(argv[
1
]);
//
Instantiate the Memory Manager class and pass in the number of blocks
//
you want on the internal free list.
MessageManager mm(n_blocks);
//
Use the Memory Manager class to assign messages and free them.
//
Run this in your favorite debug environment and you will notice that the
//
amount of memory your program uses after Memory Manager has been
//
instantiated remains the same. That means the Cached Allocator
//
controls or manages all the memory for the application.
//
Do forever.
while
(
1
)
{
//
allocate the messages somewhere
ACE_DEBUG((LM_DEBUG,
"
\n\n\nAllocating Messages\n
"
));
for
(
int
i
=
0
; i
<
n_blocks;i
++
)
{
ACE_OS::sprintf(message,
"
Message %d: Hi There
"
,i);
mm.allocate_msg(message);
}
//
show the messages
ACE_DEBUG((LM_DEBUG,
"
Displaying the messages\n
"
));
Sleep(
2
);
mm.display_all_msg();
//
free up the memory for the messages.
ACE_DEBUG((LM_DEBUG,
"
Releasing Messages\n
"
));
Sleep(
2
);
mm.free_all_msg();
}
return
0
;
}
内存池:
ACE_MMAP_Memory_Pool
ACE_MMAP_MEMORY_POOL
使用<mmap(2)>创建内存池。这样内存就可在进程间共享了。每次更新时,内存都被更新到后备存储(backing store)。
ACE_Lite_MMAP_Memory_Pool
ACE_LITE_MMAP_MEMORY_POOL
使用<mmap(2)>创建内存池。不像前面的映射,它不做后备存储更新。代价是较低可靠性。
ACE_Sbrk_Memory_Pool
ACE_SBRK_MEMORY_POOL
使用<sbrk(2)>调用创建内存池。
ACE_Shared_Memory_Pool
ACE_SHARED_MEMORY_POOL
使用系统V <shmget(2)>调用创建内存池。
Memory_Pool
内存可在进程间共享。
ACE_Local_Memory_Pool
ACE_LOCAL_MEMORY_POOL
通过C++的new和delete操作符创建局部内存池。该池不能在进程间共享。
#include
"
ace/Malloc.h
"
#include
"
ace/Malloc_T.h
"
#include
"
ace/Null_Mutex.h
"
#include
<
ACE
/
MMAP_Memory_Pool.h
>
typedef ACE_Malloc
<
ACE_MMAP_Memory_Pool,ACE_Null_Mutex
>
Malloc;
void
ReadData();
void
WriteData();
Malloc
*
g_mem;
int
main(
int
arn,
char
**
arc)
{
ACE_MMAP_Memory_Pool_Options options(ACE_DEFAULT_BASE_ADDR,
ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED,
1024
*
10000
);
ACE_NEW_RETURN(g_mem,Malloc(
"
abc
"
,
"
abc
"
,
&
options),
-
1
);
if
( arn
>
1
)
{
ReadData();
}
else
{
WriteData();
}
system(
"
pause
"
);
g_mem
->
sync();
delete g_mem;
return
0
;
}
void
ReadData()
{
char
msg[
32
]
=
{
0
}
;
void
*
data;
for
(
int
i
=
0
;i
<
10000
;i
++
)
{
sprintf(msg,
"
MSG: %d
"
,i);
if
(g_mem
->
find(msg,data)
!=
-
1
)
{
ACE_DEBUG((LM_INFO,
"
%s\n
"
,(
char
*
)data));
}
}
}
void
WriteData()
{
for
(
int
i
=
0
;i
<
10000
;i
++
)
{
char
*
buff
=
(
char
*
)g_mem
->
malloc(
1024
);
if
(buff
!=
NULL)
{
sprintf(buff,
"
MSG: %d
"
,i);
g_mem
->
bind(buff,(
void
*
)buff);
}
}
}
通过分配器接口使用Malloc类
大多数ACE中的容器类都可以接受分配器对象作为参数,以用于容器内的内存管理。因为某些内存分配方案只能用于ACE_Malloc类集,ACE含有一个适配器模板类ACE_Allocator_Adapter,它将ACE_Malloc类适配到ACE_Allocator接口。也就是说,在实例化这个模板之后创建的新类可用于替换任何ACE_Allocator。例如:
typedef ACE_Allocator_Adapter<ACE_Malloc<ACE_SHARED_MEMORY_POOL,ACE_Null_Mutex>> Allocator;