Skip to content

Commit

Permalink
feat(anomap): add anomap_clone and anomap_move
Browse files Browse the repository at this point in the history
  • Loading branch information
Anotra committed Feb 26, 2024
1 parent 8bbbd4c commit 0988de4
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
64 changes: 63 additions & 1 deletion core/anomap.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ static const struct anomap_lock null_lock = {
static unsigned anomap_has_locks =
#if !defined ANOMAP_NATIVE_LOCKS || ANOMAP_NATIVE_LOCKS == NATIVE_LOCK_NONE
0;
static const struct anomap_lock lock_functions = null_lock;
#else
anomap_use_lock;

Expand Down Expand Up @@ -288,9 +287,13 @@ anomap_init(struct anomap *map,
map->cmp = cmp;
map->keys.size = key_size;
map->vals.size = val_size;
#if !defined ANOMAP_NATIVE_LOCKS || ANOMAP_NATIVE_LOCKS == NATIVE_LOCK_NONE
map->lock.functions = &null_lock;
#else
map->lock.functions = options & anomap_use_lock
? &lock_functions
: &null_lock;
#endif
if ((map->lock.lock = map->lock.functions->create()))
return true;

Expand Down Expand Up @@ -324,6 +327,65 @@ anomap_destroy(struct anomap *map) {
free(map);
}

struct anomap *
anomap_clone(struct anomap *map, anomap_clone_options options) {
if (options) return NULL;
struct anomap *clone = malloc(sizeof *clone);
struct {
void *ptrs[16];
size_t len;
} cleanup = { 0 };
if (!clone) return NULL;

LOCK_R_ACQUIRE;
memcpy(clone, map, sizeof *clone);
clone->free_on_cleanup = true;

if (!(clone->lock.lock = clone->lock.functions->create()))
goto lock_create_fail;

#define CLONE_ARRAY(ARRAY, SIZE) \
do { \
if ((clone->ARRAY.arr = malloc(SIZE))) { \
memcpy(clone->ARRAY.arr, map->ARRAY.arr, SIZE); \
cleanup.ptrs[cleanup.len++] = clone->ARRAY.arr; \
} else goto array_copy_fail; \
} while (0)

if (clone->map.len) {
CLONE_ARRAY(map, clone->map.cap * sizeof *clone->map.arr);
CLONE_ARRAY(keys, clone->keys.cap * clone->keys.size);
if (clone->vals.size)
CLONE_ARRAY(vals, clone->vals.cap * clone->vals.size);
if (clone->options & anomap_preserve_order)
CLONE_ARRAY(order, clone->order.cap * sizeof *clone->order.arr);
}

LOCK_R_RELEASE;
return clone;

array_copy_fail:
while (cleanup.len)
free(cleanup.ptrs[--cleanup.len]);
clone->lock.functions->destroy(clone->lock.lock);
lock_create_fail:
LOCK_R_RELEASE;
free(clone);
return NULL;
}

void
anomap_move(struct anomap *dest, bool free_on_destroy, struct anomap *map) {
LOCK_W_ACQUIRE;
memcpy(dest, map, sizeof *dest);
bool free_map = map->free_on_cleanup;
dest->free_on_cleanup = free_on_destroy;
memset(map, 0, sizeof *map);
if (free_map) free(map);
map = dest;
LOCK_W_RELEASE;
}

void
anomap_set_on_item_changed(
struct anomap *map, anomap_on_item_changed *on_changed, void *data)
Expand Down
8 changes: 8 additions & 0 deletions core/anomap.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ struct anomap *anomap_create(size_t key_size, size_t val_size,
anomap_options options);
void anomap_destroy(struct anomap *map);

typedef enum {
#define ANOMAP_CLONE_OPTIONS_NONE anomap_clone_options_none
anomap_clone_options_none,
} anomap_clone_options;

struct anomap *anomap_clone(struct anomap *map, anomap_clone_options options);
void anomap_move(struct anomap *dest, bool free_on_destroy, struct anomap *map);

struct anomap_item_changed {
struct anomap *map;
void *data;
Expand Down

0 comments on commit 0988de4

Please sign in to comment.