mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-02-06 18:31:57 +08:00
Optimized the implementation of BlockHeap
This commit is contained in:
@@ -581,35 +581,14 @@ enum {
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct _BLOCKHEAP;
|
||||
|
||||
/**
|
||||
* MiniGUI's private block data heap.
|
||||
*
|
||||
* \sa InitBlockDataHeap, DestroyBlockDataHeap
|
||||
*/
|
||||
typedef struct _BLOCKHEAP
|
||||
{
|
||||
#ifdef _MGRM_THREADS
|
||||
pthread_mutex_t lock;
|
||||
#endif
|
||||
/**
|
||||
* Size of one block element.
|
||||
*/
|
||||
size_t bd_size;
|
||||
/**
|
||||
* Size of the heap in blocks.
|
||||
*/
|
||||
size_t heap_size;
|
||||
/**
|
||||
* The first free element in the heap.
|
||||
*/
|
||||
size_t free;
|
||||
/**
|
||||
* Pointer to the pre-allocated heap.
|
||||
*/
|
||||
void* heap;
|
||||
|
||||
size_t nr_alloc;
|
||||
} BLOCKHEAP;
|
||||
typedef struct _BLOCKHEAP BLOCKHEAP;
|
||||
|
||||
/**
|
||||
* \var typedef BLOCKHEAP* PBLOCKHEAP
|
||||
@@ -620,7 +599,7 @@ typedef struct _BLOCKHEAP
|
||||
typedef BLOCKHEAP* PBLOCKHEAP;
|
||||
|
||||
/**
|
||||
* \fn void InitBlockDataHeap (PBLOCKHEAP heap, \
|
||||
* \fn BOOL InitBlockDataHeap (PBLOCKHEAP heap,
|
||||
size_t bd_size, size_t heap_size)
|
||||
* \brief Initializes a private block data heap.
|
||||
*
|
||||
@@ -633,15 +612,14 @@ typedef BLOCKHEAP* PBLOCKHEAP;
|
||||
* \param bd_size The size of one block in bytes.
|
||||
* \param heap_size The size of the heap in blocks.
|
||||
*
|
||||
* \return \a heap->heap will contains a valid pointer on success,
|
||||
* NULL on error.
|
||||
* \return TRUE on success, FALSE on error.
|
||||
*
|
||||
* \note This function does not return anything. You should check the \a heap
|
||||
* field of the \a heap structure.
|
||||
*
|
||||
* \sa BLOCKHEAP
|
||||
*/
|
||||
MG_EXPORT extern void InitBlockDataHeap (PBLOCKHEAP heap,
|
||||
MG_EXPORT BOOL InitBlockDataHeap (PBLOCKHEAP heap,
|
||||
size_t bd_size, size_t heap_size);
|
||||
|
||||
/**
|
||||
@@ -659,7 +637,7 @@ MG_EXPORT extern void InitBlockDataHeap (PBLOCKHEAP heap,
|
||||
* \sa InitBlockDataHeap, BlockDataFree
|
||||
*/
|
||||
|
||||
MG_EXPORT extern void* BlockDataAlloc (PBLOCKHEAP heap);
|
||||
MG_EXPORT void* BlockDataAlloc (PBLOCKHEAP heap);
|
||||
|
||||
/**
|
||||
* \fn void BlockDataFree (PBLOCKHEAP heap, void* data)
|
||||
@@ -674,7 +652,7 @@ MG_EXPORT extern void* BlockDataAlloc (PBLOCKHEAP heap);
|
||||
*
|
||||
* \sa InitBlockDataHeap, BlockDataAlloc
|
||||
*/
|
||||
MG_EXPORT extern void BlockDataFree (PBLOCKHEAP heap, void* data);
|
||||
MG_EXPORT void BlockDataFree (PBLOCKHEAP heap, void* data);
|
||||
|
||||
/**
|
||||
* \fn void DestroyBlockDataHeap (PBLOCKHEAP heap)
|
||||
@@ -684,7 +662,7 @@ MG_EXPORT extern void BlockDataFree (PBLOCKHEAP heap, void* data);
|
||||
*
|
||||
* \sa InitBlockDataHeap, BLOCKHEAP
|
||||
*/
|
||||
MG_EXPORT extern void DestroyBlockDataHeap (PBLOCKHEAP heap);
|
||||
MG_EXPORT void DestroyBlockDataHeap (PBLOCKHEAP heap);
|
||||
|
||||
/** @} end of block_heap_fns */
|
||||
|
||||
|
||||
@@ -52,21 +52,28 @@
|
||||
#ifndef GUI_BLOCKHEAP_H
|
||||
#define GUI_BLOCKHEAP_H
|
||||
|
||||
#define BDS_FREE 0x0000
|
||||
#define BDS_SPECIAL 0x0001
|
||||
#define BDS_USED 0x0002
|
||||
|
||||
#ifndef _MGUI_GDI_H /* included in include/gdi.h */
|
||||
|
||||
typedef struct tagBLOCKHEAP {
|
||||
struct _BLOCKHEAP {
|
||||
#ifdef _MGRM_THREADS
|
||||
pthread_mutex_t lock;
|
||||
#endif
|
||||
size_t bd_size;
|
||||
size_t heap_size;
|
||||
int free;
|
||||
void* heap;
|
||||
} BLOCKHEAP;
|
||||
/* Size of one block element. */
|
||||
size_t sz_block;
|
||||
/* Size of the heap in blocks. */
|
||||
size_t sz_heap;
|
||||
/* The first free element in the heap. */
|
||||
size_t sz_usage_bmp;
|
||||
/* The number of blocks extra allocated. */
|
||||
size_t nr_alloc;
|
||||
|
||||
/* Pointer to the pre-allocated heap. */
|
||||
unsigned char* heap;
|
||||
/* Pointer to the usage bitmap. */
|
||||
unsigned char* usage_bmp;
|
||||
};
|
||||
|
||||
#ifndef _MGUI_GDI_H /* included in include/gdi.h */
|
||||
|
||||
typedef struct _BLOCKHEAP BLOCKHEAP;
|
||||
typedef BLOCKHEAP* PBLOCKHEAP;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -59,96 +59,93 @@
|
||||
#include "common.h"
|
||||
#include "minigui.h"
|
||||
#include "gdi.h"
|
||||
#include "constants.h"
|
||||
#include "blockheap.h"
|
||||
#include "misc.h"
|
||||
|
||||
void InitBlockDataHeap (PBLOCKHEAP heap, size_t bd_size, size_t heap_size)
|
||||
BOOL InitBlockDataHeap (PBLOCKHEAP heap, size_t sz_block, size_t sz_heap)
|
||||
{
|
||||
#ifdef _MGRM_THREADS
|
||||
pthread_mutex_init (&heap->lock, NULL);
|
||||
#endif
|
||||
|
||||
heap->heap = NULL;
|
||||
heap->bd_size = bd_size + sizeof (DWORD);
|
||||
heap->heap_size = heap_size;
|
||||
heap->free = 0;
|
||||
heap->sz_usage_bmp = (sz_heap + 7) >> 3;
|
||||
heap->sz_block = ROUND_TO_MULTIPLE (sz_block, SIZEOF_PTR);
|
||||
heap->sz_heap = heap->sz_usage_bmp << 3;
|
||||
|
||||
if (heap->sz_heap == 0 || heap->sz_block == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((heap->heap = calloc (heap->sz_heap, heap->sz_block)) == NULL)
|
||||
return FALSE;
|
||||
|
||||
if ((heap->usage_bmp = calloc (heap->sz_usage_bmp, sizeof (char))) == NULL) {
|
||||
free (heap->heap);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
heap->nr_alloc = 0;
|
||||
memset (heap->usage_bmp, 0xFF, heap->sz_usage_bmp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern BLOCKHEAP __mg_FreeClipRectList;
|
||||
|
||||
void* BlockDataAlloc (PBLOCKHEAP heap)
|
||||
{
|
||||
size_t i;
|
||||
char* block_data = NULL;
|
||||
int free_slot;
|
||||
unsigned char* block_data = NULL;
|
||||
|
||||
#ifdef _MGRM_THREADS
|
||||
pthread_mutex_lock (&heap->lock);
|
||||
#endif
|
||||
|
||||
if (heap->heap == NULL) {
|
||||
if (!(heap->heap = calloc (heap->heap_size, heap->bd_size)))
|
||||
goto ret;
|
||||
heap->free = 0;
|
||||
}
|
||||
free_slot = __mg_lookfor_unused_slot (heap->usage_bmp, heap->sz_usage_bmp, 1);
|
||||
if (free_slot >= 0) {
|
||||
block_data = heap->heap + heap->sz_block * free_slot;
|
||||
_DBG_PRINTF ("Allocated one block in the block heap: %p (%d)\n",
|
||||
heap, free_slot);
|
||||
|
||||
block_data = (char*) heap->heap + heap->bd_size*heap->free;
|
||||
for (i = heap->free; i < heap->heap_size; i++) {
|
||||
|
||||
if (*((DWORD*)block_data) == BDS_FREE) {
|
||||
|
||||
heap->free = i + 1;
|
||||
*((DWORD*)block_data) = BDS_USED;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
block_data += heap->bd_size;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (!(block_data = calloc (1, heap->bd_size)))
|
||||
goto ret;
|
||||
#else
|
||||
if (!(block_data = mg_slice_alloc0 (heap->bd_size)))
|
||||
goto ret;
|
||||
#if 0
|
||||
if (!mgIsServer && heap == &__mg_FreeClipRectList && free_slot == 5)
|
||||
assert (0);
|
||||
#endif
|
||||
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if ((block_data = calloc (1, heap->sz_block)) == NULL)
|
||||
goto ret;
|
||||
heap->nr_alloc++;
|
||||
|
||||
*((DWORD*)block_data) = BDS_SPECIAL;
|
||||
|
||||
ret:
|
||||
|
||||
#ifdef _MGRM_THREADS
|
||||
pthread_mutex_unlock (&heap->lock);
|
||||
#endif
|
||||
|
||||
if (block_data)
|
||||
return block_data + sizeof (DWORD);
|
||||
return NULL;
|
||||
return block_data;
|
||||
}
|
||||
|
||||
void BlockDataFree (PBLOCKHEAP heap, void* data)
|
||||
{
|
||||
size_t i;
|
||||
char* block_data;
|
||||
unsigned char* block_data = data;
|
||||
|
||||
#ifdef _MGRM_THREADS
|
||||
pthread_mutex_lock (&heap->lock);
|
||||
#endif
|
||||
|
||||
block_data = (char*) data - sizeof (DWORD);
|
||||
if (*((DWORD*)block_data) == BDS_SPECIAL) {
|
||||
#if 1
|
||||
if (block_data < heap->heap ||
|
||||
block_data > (heap->heap + heap->sz_block * heap->sz_heap)) {
|
||||
free (block_data);
|
||||
#else
|
||||
mg_slice_free (heap->bd_size, block_data);
|
||||
heap->nr_alloc--;
|
||||
#endif
|
||||
}
|
||||
else if (*((DWORD*)block_data) == BDS_USED) {
|
||||
*((DWORD*)block_data) = BDS_FREE;
|
||||
else {
|
||||
int slot;
|
||||
slot = (block_data - heap->heap) / heap->sz_block;
|
||||
__mg_slot_clear_use (heap->usage_bmp, slot);
|
||||
|
||||
i = (block_data - (char*)heap->heap)/heap->bd_size;
|
||||
if (heap->free > i)
|
||||
heap->free = i;
|
||||
_DBG_PRINTF ("Freed one block in the block heap: %p (%d)\n",
|
||||
heap, slot);
|
||||
}
|
||||
|
||||
#ifdef _MGRM_THREADS
|
||||
@@ -158,9 +155,45 @@ void BlockDataFree (PBLOCKHEAP heap, void* data)
|
||||
|
||||
void DestroyBlockDataHeap (PBLOCKHEAP heap)
|
||||
{
|
||||
int nr_free_slots;
|
||||
|
||||
if (heap->nr_alloc > 0) {
|
||||
_WRN_PRINTF ("There are still not freed extra blocks in the block heap: %p (%zu)\n",
|
||||
heap, heap->nr_alloc);
|
||||
}
|
||||
|
||||
nr_free_slots = __mg_get_nr_idle_slots (heap->usage_bmp, heap->sz_usage_bmp);
|
||||
if (nr_free_slots != heap->sz_heap) {
|
||||
_WRN_PRINTF ("There are still not freed blocks in the block heap: %p (%zu)\n",
|
||||
heap, heap->sz_heap - nr_free_slots);
|
||||
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
unsigned char* bitmap = heap->usage_bmp;
|
||||
int slot = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < heap->sz_usage_bmp; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (!(*bitmap & (0x80 >> j))) {
|
||||
_WRN_PRINTF ("Still used slot in the block heap: %p (%d)\n",
|
||||
heap, slot);
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
bitmap++;
|
||||
}
|
||||
}
|
||||
|
||||
assert (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
free (heap->heap);
|
||||
free (heap->usage_bmp);
|
||||
|
||||
#ifdef _MGRM_THREADS
|
||||
pthread_mutex_destroy (&heap->lock);
|
||||
#endif
|
||||
free (heap->heap);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user