mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-18 08:20:36 +01:00
[skiplist] Allocate elements in chunks.
Use a pool allocator to preallocate a chunk from which to allocate the skiplist elements (if we failed to reallocate from the freelists).
This commit is contained in:
parent
903b39c304
commit
2b7c6f361a
3 changed files with 94 additions and 27 deletions
|
|
@ -966,10 +966,13 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
|
|||
int i;
|
||||
cairo_bo_event_t *events, **sorted_event_ptrs;
|
||||
unsigned num_events = 2*num_edges;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_skip_list_init (&event_queue->intersection_queue,
|
||||
cairo_bo_event_compare_abstract,
|
||||
sizeof (cairo_bo_event_t));
|
||||
status = _cairo_skip_list_init (&event_queue->intersection_queue,
|
||||
cairo_bo_event_compare_abstract,
|
||||
sizeof (cairo_bo_event_t));
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* The skip_elt_t field of a cairo_bo_event_t isn't used for start
|
||||
* or stop events, so this allocation is safe. XXX: make the
|
||||
|
|
@ -1053,15 +1056,22 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
|
|||
return _cairo_bo_event_queue_insert (event_queue, &event);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
|
||||
{
|
||||
_cairo_skip_list_init (&sweep_line->active_edges,
|
||||
_sweep_line_elt_compare,
|
||||
sizeof (sweep_line_elt_t));
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_skip_list_init (&sweep_line->active_edges,
|
||||
_sweep_line_elt_compare,
|
||||
sizeof (sweep_line_elt_t));
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
sweep_line->head = NULL;
|
||||
sweep_line->tail = NULL;
|
||||
sweep_line->current_y = 0;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1110,7 +1120,8 @@ _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line,
|
|||
{
|
||||
cairo_bo_edge_t **left_next, **right_prev;
|
||||
|
||||
_cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
|
||||
_cairo_skip_list_delete_given (&sweep_line->active_edges,
|
||||
&edge->sweep_line_elt->elt);
|
||||
|
||||
left_next = &sweep_line->head;
|
||||
if (edge->prev)
|
||||
|
|
@ -1495,7 +1506,10 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_bo_sweep_line_init (&sweep_line);
|
||||
status = _cairo_bo_sweep_line_init (&sweep_line);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_EVENT_QUEUE;
|
||||
|
||||
_cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
|
||||
|
||||
#if DEBUG_PRINT_STATE
|
||||
|
|
@ -1621,6 +1635,7 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
}
|
||||
_cairo_bo_traps_fini (&bo_traps);
|
||||
_cairo_bo_sweep_line_fini (&sweep_line);
|
||||
CLEANUP_EVENT_QUEUE:
|
||||
_cairo_bo_event_queue_fini (&event_queue);
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ typedef struct _skip_list {
|
|||
size_t data_size;
|
||||
skip_elt_t *chains[MAX_LEVEL];
|
||||
skip_elt_t *freelists[MAX_FREELIST_LEVEL];
|
||||
struct pool *pool;
|
||||
int max_level;
|
||||
} cairo_skip_list_t;
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ typedef struct _skip_list {
|
|||
* sizeof) is passed for elt_size. Note that the structure used for
|
||||
* list elements must have as its final member a skip_elt_t
|
||||
*/
|
||||
cairo_private void
|
||||
cairo_private cairo_status_t
|
||||
_cairo_skip_list_init (cairo_skip_list_t *list,
|
||||
cairo_skip_list_compare_t compare,
|
||||
size_t elt_size);
|
||||
|
|
|
|||
|
|
@ -38,10 +38,42 @@ hars_petruska_f54_1_random (void)
|
|||
# undef rol
|
||||
}
|
||||
|
||||
struct pool {
|
||||
struct pool *next;
|
||||
char *ptr;
|
||||
unsigned int rem;
|
||||
};
|
||||
|
||||
static struct pool *
|
||||
pool_new (void)
|
||||
{
|
||||
struct pool *pool;
|
||||
|
||||
pool = malloc (8192 - 8);
|
||||
if (unlikely (pool == NULL))
|
||||
return NULL;
|
||||
|
||||
pool->next = NULL;
|
||||
pool->rem = 8192 - 8 - sizeof (struct pool);
|
||||
pool->ptr = (char *) (pool + 1);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void
|
||||
pools_destroy (struct pool *pool)
|
||||
{
|
||||
while (pool != NULL) {
|
||||
struct pool *next = pool->next;
|
||||
free (pool);
|
||||
pool = next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize an empty skip list
|
||||
*/
|
||||
void
|
||||
cairo_status_t
|
||||
_cairo_skip_list_init (cairo_skip_list_t *list,
|
||||
cairo_skip_list_compare_t compare,
|
||||
size_t elt_size)
|
||||
|
|
@ -51,6 +83,9 @@ _cairo_skip_list_init (cairo_skip_list_t *list,
|
|||
list->compare = compare;
|
||||
list->elt_size = elt_size;
|
||||
list->data_size = elt_size - sizeof (skip_elt_t);
|
||||
list->pool = pool_new ();
|
||||
if (unlikely (list->pool == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
for (i = 0; i < MAX_LEVEL; i++) {
|
||||
list->chains[i] = NULL;
|
||||
|
|
@ -61,25 +96,14 @@ _cairo_skip_list_init (cairo_skip_list_t *list,
|
|||
}
|
||||
|
||||
list->max_level = 0;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_skip_list_fini (cairo_skip_list_t *list)
|
||||
{
|
||||
skip_elt_t *elt;
|
||||
int i;
|
||||
|
||||
while ((elt = list->chains[0])) {
|
||||
_cairo_skip_list_delete_given (list, elt);
|
||||
}
|
||||
for (i=0; i<MAX_FREELIST_LEVEL; i++) {
|
||||
elt = list->freelists[i];
|
||||
while (elt) {
|
||||
skip_elt_t *nextfree = elt->prev;
|
||||
free (ELT_DATA(elt));
|
||||
elt = nextfree;
|
||||
}
|
||||
}
|
||||
pools_destroy (list->pool);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -109,6 +133,34 @@ random_level (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void *
|
||||
pool_alloc (cairo_skip_list_t *list,
|
||||
unsigned int level)
|
||||
{
|
||||
unsigned int size;
|
||||
struct pool *pool;
|
||||
void *ptr;
|
||||
|
||||
size = list->elt_size +
|
||||
(FREELIST_MAX_LEVEL_FOR (level) - 1) * sizeof (skip_elt_t *);
|
||||
|
||||
pool = list->pool;
|
||||
if (size > pool->rem) {
|
||||
pool = pool_new ();
|
||||
if (unlikely (pool == NULL))
|
||||
return NULL;
|
||||
|
||||
pool->next = list->pool;
|
||||
list->pool = pool;
|
||||
}
|
||||
|
||||
ptr = pool->ptr;
|
||||
pool->ptr += size;
|
||||
pool->rem -= size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *
|
||||
alloc_node_for_level (cairo_skip_list_t *list, unsigned level)
|
||||
{
|
||||
|
|
@ -118,8 +170,7 @@ alloc_node_for_level (cairo_skip_list_t *list, unsigned level)
|
|||
list->freelists[freelist_level] = elt->prev;
|
||||
return ELT_DATA(elt);
|
||||
}
|
||||
return malloc (list->elt_size
|
||||
+ (FREELIST_MAX_LEVEL_FOR (level) - 1) * sizeof (skip_elt_t *));
|
||||
return pool_alloc (list, level);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue