mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Redo gtables to prevent reduce number of mallocs and frees.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3024 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
cc40000313
commit
2bba3b8d26
@ -52,25 +52,24 @@ gnc_cellblock_new (int rows, int cols)
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
static gpointer
|
||||
gnc_cellblock_cell_new (gpointer user_data)
|
||||
static void
|
||||
gnc_cellblock_cell_construct (gpointer _cb_cell, gpointer user_data)
|
||||
{
|
||||
CellBlockCell *cb_cell;
|
||||
|
||||
cb_cell = g_new0(CellBlockCell, 1);
|
||||
CellBlockCell *cb_cell = _cb_cell;
|
||||
|
||||
cb_cell->cell = NULL;
|
||||
cb_cell->cell_type = -1;
|
||||
|
||||
cb_cell->sample_text = NULL;
|
||||
cb_cell->alignment = CELL_ALIGN_LEFT;
|
||||
cb_cell->expandable = FALSE;
|
||||
cb_cell->span = FALSE;
|
||||
|
||||
return cb_cell;
|
||||
}
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
static void
|
||||
gnc_cellblock_cell_free (gpointer _cb_cell, gpointer user_data)
|
||||
gnc_cellblock_cell_destroy (gpointer _cb_cell, gpointer user_data)
|
||||
{
|
||||
CellBlockCell *cb_cell = _cb_cell;
|
||||
|
||||
@ -79,10 +78,6 @@ gnc_cellblock_cell_free (gpointer _cb_cell, gpointer user_data)
|
||||
|
||||
g_free(cb_cell->sample_text);
|
||||
cb_cell->sample_text = NULL;
|
||||
|
||||
g_free(cb_cell);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* =================================================== */
|
||||
@ -100,8 +95,9 @@ gnc_cellblock_init (CellBlock *cellblock, int rows, int cols)
|
||||
cellblock->num_cols = cols;
|
||||
|
||||
/* malloc new cell table */
|
||||
cellblock->cb_cells = g_table_new (gnc_cellblock_cell_new,
|
||||
gnc_cellblock_cell_free, NULL);
|
||||
cellblock->cb_cells = g_table_new (sizeof (CellBlockCell),
|
||||
gnc_cellblock_cell_construct,
|
||||
gnc_cellblock_cell_destroy, NULL);
|
||||
g_table_resize (cellblock->cb_cells, rows, cols);
|
||||
}
|
||||
|
||||
|
@ -1895,7 +1895,7 @@ gnucash_sheet_set_scroll_region (GnucashSheet *sheet)
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_block_free (gpointer _block, gpointer user_data)
|
||||
gnucash_sheet_block_destroy (gpointer _block, gpointer user_data)
|
||||
{
|
||||
SheetBlock *block = _block;
|
||||
|
||||
@ -1906,18 +1906,14 @@ gnucash_sheet_block_free (gpointer _block, gpointer user_data)
|
||||
gnucash_style_unref (block->style);
|
||||
block->style = NULL;
|
||||
}
|
||||
|
||||
g_free (block);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gnucash_sheet_block_new (gpointer user_data)
|
||||
static void
|
||||
gnucash_sheet_block_construct (gpointer _block, gpointer user_data)
|
||||
{
|
||||
SheetBlock *block;
|
||||
SheetBlock *block = _block;
|
||||
|
||||
block = g_new0 (SheetBlock, 1);
|
||||
|
||||
return block;
|
||||
block->style = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2122,8 +2118,9 @@ gnucash_sheet_init (GnucashSheet *sheet)
|
||||
sheet->height = 0;
|
||||
sheet->smooth_scroll = TRUE;
|
||||
|
||||
sheet->blocks = g_table_new(gnucash_sheet_block_new,
|
||||
gnucash_sheet_block_free, NULL);
|
||||
sheet->blocks = g_table_new(sizeof (SheetBlock),
|
||||
gnucash_sheet_block_construct,
|
||||
gnucash_sheet_block_destroy, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,24 +66,15 @@ style_get_key (SheetBlockStyle *style)
|
||||
}
|
||||
|
||||
|
||||
static gpointer
|
||||
cell_dimensions_new (gpointer user_data)
|
||||
static void
|
||||
cell_dimensions_construct (gpointer _cd, gpointer user_data)
|
||||
{
|
||||
CellDimensions *cd;
|
||||
|
||||
cd = g_new0 (CellDimensions, 1);
|
||||
CellDimensions *cd = _cd;
|
||||
|
||||
cd->pixel_width = -1;
|
||||
cd->can_span_over = TRUE;
|
||||
|
||||
return cd;
|
||||
}
|
||||
|
||||
static void
|
||||
cell_dimensions_free (gpointer cd, gpointer user_data)
|
||||
{
|
||||
g_free(cd);
|
||||
}
|
||||
|
||||
static BlockDimensions *
|
||||
style_dimensions_new (SheetBlockStyle *style)
|
||||
@ -95,8 +86,9 @@ style_dimensions_new (SheetBlockStyle *style)
|
||||
dimensions->nrows = style->nrows;
|
||||
dimensions->ncols = style->ncols;
|
||||
|
||||
dimensions->cell_dimensions = g_table_new (cell_dimensions_new,
|
||||
cell_dimensions_free, NULL);
|
||||
dimensions->cell_dimensions = g_table_new (sizeof (CellDimensions),
|
||||
cell_dimensions_construct,
|
||||
NULL, NULL);
|
||||
|
||||
g_table_resize (dimensions->cell_dimensions,
|
||||
style->nrows, style->ncols);
|
||||
@ -627,25 +619,23 @@ gnucash_style_get_cell_style (SheetBlockStyle *style, int row, int col)
|
||||
return g_table_index (style->cell_styles, row, col);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
cell_style_new (gpointer user_data)
|
||||
static void
|
||||
cell_style_construct (gpointer _cs, gpointer user_data)
|
||||
{
|
||||
CellStyle *cs;
|
||||
CellStyle *cs = _cs;
|
||||
|
||||
cs = g_new0 (CellStyle, 1);
|
||||
|
||||
return cs;
|
||||
cs->label = NULL;
|
||||
cs->active_bg_color = NULL;
|
||||
cs->inactive_bg_color = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
cell_style_free (gpointer _cs, gpointer user_data)
|
||||
cell_style_destroy (gpointer _cs, gpointer user_data)
|
||||
{
|
||||
CellStyle *cs = _cs;
|
||||
|
||||
g_free(cs->label);
|
||||
cs->label = NULL;
|
||||
|
||||
g_free(cs);
|
||||
}
|
||||
|
||||
static SheetBlockStyle *
|
||||
@ -669,8 +659,9 @@ gnucash_sheet_style_new (GnucashSheet *sheet, CellBlock *cursor,
|
||||
style->nrows = cursor->num_rows;
|
||||
style->ncols = cursor->num_cols;
|
||||
|
||||
style->cell_styles = g_table_new (cell_style_new,
|
||||
cell_style_free, NULL);
|
||||
style->cell_styles = g_table_new (sizeof (CellStyle),
|
||||
cell_style_construct,
|
||||
cell_style_destroy, NULL);
|
||||
g_table_resize (style->cell_styles, style->nrows, style->ncols);
|
||||
|
||||
gnucash_sheet_style_recompile(style, sr, cursor_type);
|
||||
|
@ -25,36 +25,38 @@
|
||||
|
||||
struct GTable
|
||||
{
|
||||
GPtrArray *array;
|
||||
GArray *array;
|
||||
|
||||
guint entry_size;
|
||||
|
||||
int rows;
|
||||
int cols;
|
||||
|
||||
g_table_allocator allocator;
|
||||
g_table_deallocator deallocator;
|
||||
g_table_entry_constructor constructor;
|
||||
g_table_entry_destroyer destroyer;
|
||||
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
GTable *
|
||||
g_table_new (g_table_allocator allocator,
|
||||
g_table_deallocator deallocator,
|
||||
g_table_new (guint entry_size,
|
||||
g_table_entry_constructor constructor,
|
||||
g_table_entry_destroyer destroyer,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTable *gtable;
|
||||
|
||||
g_assert (allocator);
|
||||
g_assert (deallocator);
|
||||
|
||||
gtable = g_new(GTable, 1);
|
||||
|
||||
gtable->array = g_ptr_array_new();
|
||||
gtable->array = g_array_new(FALSE, FALSE, entry_size);
|
||||
|
||||
gtable->entry_size = entry_size;
|
||||
|
||||
gtable->rows = 0;
|
||||
gtable->cols = 0;
|
||||
|
||||
gtable->allocator = allocator;
|
||||
gtable->deallocator = deallocator;
|
||||
gtable->constructor = constructor;
|
||||
gtable->destroyer = destroyer;
|
||||
|
||||
gtable->user_data = user_data;
|
||||
|
||||
@ -69,7 +71,7 @@ g_table_destroy (GTable *gtable)
|
||||
|
||||
g_table_resize (gtable, 0, 0);
|
||||
|
||||
g_ptr_array_free (gtable->array, FALSE);
|
||||
g_array_free (gtable->array, TRUE);
|
||||
|
||||
gtable->array = NULL;
|
||||
|
||||
@ -90,9 +92,9 @@ g_table_index (GTable *gtable, int row, int col)
|
||||
if (col >= gtable->cols)
|
||||
return NULL;
|
||||
|
||||
index = (row * gtable->cols) + col;
|
||||
index = ((row * gtable->cols) + col) * gtable->entry_size;
|
||||
|
||||
return gtable->array->pdata[index];
|
||||
return >able->array->data[index];
|
||||
}
|
||||
|
||||
void
|
||||
@ -112,29 +114,35 @@ g_table_resize (GTable *gtable, int rows, int cols)
|
||||
if (new_len == old_len)
|
||||
return;
|
||||
|
||||
/* If shrinking, free extra cells */
|
||||
if (new_len < old_len)
|
||||
/* If shrinking, destroy extra cells */
|
||||
if ((new_len < old_len) && gtable->destroyer)
|
||||
{
|
||||
gpointer *tcp;
|
||||
gchar *entry;
|
||||
guint i;
|
||||
|
||||
tcp = >able->array->pdata[new_len];
|
||||
for (i = new_len; i < old_len; i++, tcp++)
|
||||
gtable->deallocator(*tcp, gtable->user_data);
|
||||
entry = >able->array->data[new_len * gtable->entry_size];
|
||||
for (i = new_len; i < old_len; i++)
|
||||
{
|
||||
gtable->destroyer(entry, gtable->user_data);
|
||||
entry += gtable->entry_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Change the size */
|
||||
g_ptr_array_set_size(gtable->array, new_len);
|
||||
g_array_set_size(gtable->array, new_len);
|
||||
|
||||
/* If expanding, create the new cells */
|
||||
if (new_len > old_len)
|
||||
/* If expanding, construct the new cells */
|
||||
if ((new_len > old_len) && gtable->constructor)
|
||||
{
|
||||
gpointer *tcp;
|
||||
gchar *entry;
|
||||
guint i;
|
||||
|
||||
tcp = >able->array->pdata[old_len];
|
||||
for (i = old_len; i < new_len; i++, tcp++)
|
||||
*tcp = gtable->allocator(gtable->user_data);
|
||||
entry = >able->array->data[old_len * gtable->entry_size];
|
||||
for (i = old_len; i < new_len; i++)
|
||||
{
|
||||
gtable->constructor(entry, gtable->user_data);
|
||||
entry += gtable->entry_size;
|
||||
}
|
||||
}
|
||||
|
||||
gtable->rows = rows;
|
||||
|
@ -31,15 +31,16 @@
|
||||
|
||||
typedef struct GTable GTable;
|
||||
|
||||
typedef gpointer (*g_table_allocator) (gpointer user_data);
|
||||
typedef void (*g_table_deallocator) (gpointer entry, gpointer user_data);
|
||||
typedef void (*g_table_entry_constructor) (gpointer entry, gpointer user_data);
|
||||
typedef void (*g_table_entry_destroyer) (gpointer entry, gpointer user_data);
|
||||
|
||||
|
||||
/* Create a new table with the given allocator and deallocator.
|
||||
* Both functions must be given. They are used to populate the
|
||||
* table and free extra members when resizing and destroying. */
|
||||
GTable * g_table_new (g_table_allocator allocator,
|
||||
g_table_deallocator deallocator,
|
||||
/* Create a new table with the given entry constructor and destroyer.
|
||||
* Both functions must be given. They are used to initialize the table
|
||||
* entries and free unneeded memory when resizing and destroying. */
|
||||
GTable * g_table_new (guint entry_size,
|
||||
g_table_entry_constructor constructor,
|
||||
g_table_entry_destroyer destroyer,
|
||||
gpointer user_data);
|
||||
|
||||
/* Free the table and all associated table elements. */
|
||||
|
@ -41,30 +41,18 @@
|
||||
#include "util.h"
|
||||
|
||||
|
||||
/** Datatypes **********************************************************/
|
||||
|
||||
/* The generic TableCell is used for memory allocation purposes. */
|
||||
typedef union _TableCell TableCell;
|
||||
union _TableCell
|
||||
{
|
||||
VirtualCell virt_cell;
|
||||
};
|
||||
|
||||
|
||||
/** Static Globals *****************************************************/
|
||||
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
static short module = MOD_REGISTER;
|
||||
|
||||
static GMemChunk *cell_mem_chunk = NULL;
|
||||
|
||||
|
||||
/** Prototypes *********************************************************/
|
||||
static void gnc_table_init (Table * table);
|
||||
static void gnc_table_free_data (Table * table);
|
||||
static gpointer gnc_virtual_cell_new (gpointer user_data);
|
||||
static void gnc_virtual_cell_construct (gpointer vcell, gpointer user_data);
|
||||
static void gnc_virtual_location_init (VirtualLocation *vloc);
|
||||
static void gnc_virtual_cell_free (gpointer tcell, gpointer user_data);
|
||||
static void gnc_virtual_cell_destroy (gpointer vcell, gpointer user_data);
|
||||
static void gnc_table_resize (Table * table, int virt_rows, int virt_cols);
|
||||
|
||||
|
||||
@ -82,10 +70,6 @@ gnc_table_new (TableGetEntryHandler entry_handler,
|
||||
|
||||
g_assert (entry_handler != NULL);
|
||||
|
||||
/* Do this here for lower overhead. */
|
||||
if (cell_mem_chunk == NULL)
|
||||
cell_mem_chunk = g_mem_chunk_create(TableCell, 2048, G_ALLOC_AND_FREE);
|
||||
|
||||
table = g_new0(Table, 1);
|
||||
|
||||
table->entry_handler = entry_handler;
|
||||
@ -97,8 +81,9 @@ gnc_table_new (TableGetEntryHandler entry_handler,
|
||||
|
||||
gnc_table_init (table);
|
||||
|
||||
table->virt_cells = g_table_new(gnc_virtual_cell_new,
|
||||
gnc_virtual_cell_free, table);
|
||||
table->virt_cells = g_table_new(sizeof (VirtualCell),
|
||||
gnc_virtual_cell_construct,
|
||||
gnc_virtual_cell_destroy, table);
|
||||
|
||||
return table;
|
||||
}
|
||||
@ -158,18 +143,11 @@ gnc_table_destroy (Table * table)
|
||||
VirtualCell *
|
||||
gnc_table_get_virtual_cell (Table *table, VirtualCellLocation vcell_loc)
|
||||
{
|
||||
TableCell *tcell;
|
||||
|
||||
if (table == NULL)
|
||||
return NULL;
|
||||
|
||||
tcell = g_table_index (table->virt_cells,
|
||||
vcell_loc.virt_row, vcell_loc.virt_col);
|
||||
|
||||
if (tcell == NULL)
|
||||
return NULL;
|
||||
|
||||
return &tcell->virt_cell;
|
||||
return g_table_index (table->virt_cells,
|
||||
vcell_loc.virt_row, vcell_loc.virt_col);
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
@ -371,16 +349,11 @@ gnc_virtual_location_init (VirtualLocation *vloc)
|
||||
|
||||
/* ==================================================== */
|
||||
|
||||
static gpointer
|
||||
gnc_virtual_cell_new (gpointer user_data)
|
||||
static void
|
||||
gnc_virtual_cell_construct (gpointer _vcell, gpointer user_data)
|
||||
{
|
||||
VirtualCell *vcell = _vcell;
|
||||
Table *table = user_data;
|
||||
TableCell *tcell;
|
||||
VirtualCell *vcell;
|
||||
|
||||
tcell = g_chunk_new(TableCell, cell_mem_chunk);
|
||||
|
||||
vcell = &tcell->virt_cell;
|
||||
|
||||
vcell->cellblock = NULL;
|
||||
|
||||
@ -388,30 +361,20 @@ gnc_virtual_cell_new (gpointer user_data)
|
||||
vcell->vcell_data = table->vcell_data_allocator();
|
||||
else
|
||||
vcell->vcell_data = NULL;
|
||||
|
||||
return tcell;
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
|
||||
static void
|
||||
gnc_virtual_cell_free (gpointer _tcell, gpointer user_data)
|
||||
gnc_virtual_cell_destroy (gpointer _vcell, gpointer user_data)
|
||||
{
|
||||
VirtualCell *vcell = _vcell;
|
||||
Table *table = user_data;
|
||||
TableCell *tcell = _tcell;
|
||||
VirtualCell *vcell;
|
||||
|
||||
if (tcell == NULL)
|
||||
return;
|
||||
|
||||
vcell = &tcell->virt_cell;
|
||||
|
||||
if (vcell->vcell_data && table && table->vcell_data_deallocator)
|
||||
table->vcell_data_deallocator (vcell->vcell_data);
|
||||
|
||||
vcell->vcell_data = NULL;
|
||||
|
||||
g_mem_chunk_free(cell_mem_chunk, tcell);
|
||||
}
|
||||
|
||||
/* ==================================================== */
|
||||
|
Loading…
Reference in New Issue
Block a user