예제 #1
0
/* Add an operation to the queue for tile @index
 * Note: if an operation affects more than one tile, it must be added once per tile.
 *
 * Concurrency: This function is not thread-safe on the same @self instance. */
void
operation_queue_add(OperationQueue *self, TileIndex index, OperationDataDrawDab *op)
{
    while (!tile_map_contains(self->tile_map, index)) {
#ifdef HEAVY_DEBUG
        operation_queue_resize(self, self->tile_map->size+1);
#else
        operation_queue_resize(self, self->tile_map->size*2);
#endif
    }

    Fifo **queue_pointer = (Fifo **)tile_map_get(self->tile_map, index);
    Fifo *op_queue = *queue_pointer;

    if (op_queue == NULL) {
        // Lazy initialization
        op_queue = fifo_new();
        *queue_pointer = op_queue;
    }

    if (fifo_peek_first(op_queue) == NULL) {
        // Critical section, not thread-safe
       if (!(self->dirty_tiles_n < self->tile_map->size*2*self->tile_map->size*2)) {
           // Prune duplicate tiles that cause us to almost exceed max
           self->dirty_tiles_n = remove_duplicate_tiles(self->dirty_tiles, self->dirty_tiles_n);
       }
       assert(self->dirty_tiles_n < self->tile_map->size*2*self->tile_map->size*2);
       self->dirty_tiles[self->dirty_tiles_n++] = index;
    }
    fifo_push(op_queue, (void *)op);
}
예제 #2
0
/* Pop an operation off the queue for tile @index
 * The user of this function is reponsible for freeing the result using free()
 *
 * Concurrency: This function is reentrant (and lock-free) on different @index */
OperationDataDrawDab *
operation_queue_pop(OperationQueue *self, TileIndex index)
{
    OperationDataDrawDab *op = NULL;

    if (!tile_map_contains(self->tile_map, index)) {
        return NULL;
    }

    Fifo **queue_pointer = tile_map_get(self->tile_map, index);
    Fifo *op_queue = *queue_pointer;

    if (!op_queue) {
        return NULL;
    }

    op = fifo_pop(op_queue);
    if (!op) {
        // Queue empty
        fifo_free(op_queue, operation_delete_func);
        *queue_pointer = NULL;
        return NULL;
    } else {
        assert(op != NULL);
        return op;
    }
}
예제 #3
0
OperationDataDrawDab *
operation_queue_peek_last(OperationQueue *self, TileIndex index) {
    if (!tile_map_contains(self->tile_map, index)) {
        return NULL;
    }

    Fifo *op_queue = (Fifo *)*tile_map_get(self->tile_map, index);
    return (!op_queue) ? NULL : (OperationDataDrawDab *)fifo_peek_last(op_queue);
}