Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ OBJECTS=CK_ARRAY_FOREACH \
ck_rhs_grow \
ck_rhs_rebuild \
ck_rhs_count \
ck_rhs_map_size \
ck_rhs_reset \
ck_rhs_reset_preallocated \
ck_rhs_reset_size \
ck_rhs_stat \
ck_rwcohort \
Expand Down
63 changes: 63 additions & 0 deletions doc/ck_rhs_map_size
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
.\"
.\" Copyright 2012-2013 Samy Al Bahra.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\"
.Dd April 26, 2026
.Dt CK_RHS_MAP_SIZE 3
.Sh NAME
.Nm ck_rhs_map_size
.Nd return the backing map allocation size for a hash set capacity
.Sh LIBRARY
Concurrency Kit (libck, \-lck)
.Sh SYNOPSIS
.In ck_rhs.h
.Ft size_t
.Fn ck_rhs_map_size "ck_rhs_t *hs" "unsigned long size"
.Sh DESCRIPTION
The
.Fn ck_rhs_map_size 3
function returns the number of bytes required for backing memory
capable of storing a hash set with enough capacity for
.Fa size
entries using the configuration of
.Fa hs .
.Pp
This is intended to size caller-managed backing memory for
.Xr ck_rhs_reset_preallocated 3 .
.Sh RETURN VALUES
The
.Fn ck_rhs_map_size 3
function returns the required backing allocation size in bytes.
.Sh ERRORS
Behavior is undefined if
.Fa hs
is uninitialized.
.Sh SEE ALSO
.Xr ck_rhs_init 3 ,
.Xr ck_rhs_reset 3 ,
.Xr ck_rhs_reset_size 3 ,
.Xr ck_rhs_reset_preallocated 3
.Pp
Additional information available at http://concurrencykit.org/
2 changes: 2 additions & 0 deletions doc/ck_rhs_reset
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ thread.
.Xr ck_rhs_set 3 ,
.Xr ck_rhs_fas 3 ,
.Xr ck_rhs_remove 3 ,
.Xr ck_rhs_map_size 3 ,
.Xr ck_rhs_reset_preallocated 3 ,
.Xr ck_rhs_reset_size 3 ,
.Xr ck_rhs_grow 3 ,
.Xr ck_rhs_gc 3 ,
Expand Down
77 changes: 77 additions & 0 deletions doc/ck_rhs_reset_preallocated
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.\"
.\" Copyright 2012-2013 Samy Al Bahra.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\"
.Dd April 26, 2026
.Dt CK_RHS_RESET_PREALLOCATED 3
.Sh NAME
.Nm ck_rhs_reset_preallocated
.Nd remove all keys from a hash set using caller-provided backing memory
.Sh LIBRARY
Concurrency Kit (libck, \-lck)
.Sh SYNOPSIS
.In ck_rhs.h
.Ft void
.Fn ck_rhs_reset_preallocated "ck_rhs_t *hs" "unsigned long size" "void *memory"
.Sh DESCRIPTION
The
.Fn ck_rhs_reset_preallocated 3
function removes all keys stored in the hash set pointed to by the
.Fa hs
argument and creates a new generation of the hash set that is backed by
the caller-provided
.Fa memory
buffer.
.Pp
The
.Fa memory
argument must be non-NULL and must refer to a region of at least
.Fn ck_rhs_map_size 3
bytes for the requested
.Fa size
and hash set configuration. The allocation referenced by
.Fa memory
must be safe to reclaim through the
.Li free
callback configured for
.Fa hs .
Ownership of this backing memory is transferred to the hash set and it
will later be reclaimed through that callback.
.Sh RETURN VALUES
This function does not return a value.
.Sh ERRORS
Behavior is undefined if
.Fa hs
is uninitialized. Behavior is undefined if
.Fa memory
is NULL or too small for the requested capacity. Behavior is undefined
if this function is called by a non-writer thread.
.Sh SEE ALSO
.Xr ck_rhs_init 3 ,
.Xr ck_rhs_map_size 3 ,
.Xr ck_rhs_reset 3 ,
.Xr ck_rhs_reset_size 3
.Pp
Additional information available at http://concurrencykit.org/
2 changes: 2 additions & 0 deletions doc/ck_rhs_reset_size
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,13 @@ thread.
.Xr ck_rhs_set 3 ,
.Xr ck_rhs_fas 3 ,
.Xr ck_rhs_remove 3 ,
.Xr ck_rhs_map_size 3 ,
.Xr ck_rhs_grow 3 ,
.Xr ck_rhs_gc 3 ,
.Xr ck_rhs_rebuild 3 ,
.Xr ck_rhs_count 3 ,
.Xr ck_rhs_reset 3 ,
.Xr ck_rhs_reset_preallocated 3 ,
.Xr ck_rhs_stat 3
.Pp
Additional information available at http://concurrencykit.org/
2 changes: 2 additions & 0 deletions include/ck_rhs.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ bool ck_rhs_grow(ck_rhs_t *, unsigned long);
bool ck_rhs_rebuild(ck_rhs_t *);
bool ck_rhs_gc(ck_rhs_t *);
unsigned long ck_rhs_count(ck_rhs_t *);
size_t ck_rhs_map_size(ck_rhs_t *, unsigned long);
bool ck_rhs_reset(ck_rhs_t *);
bool ck_rhs_reset_size(ck_rhs_t *, unsigned long);
void ck_rhs_reset_preallocated(ck_rhs_t *, unsigned long, void *);
void ck_rhs_stat(ck_rhs_t *, struct ck_rhs_stat *);
bool ck_rhs_set_load_factor(ck_rhs_t *, unsigned int);

Expand Down
34 changes: 34 additions & 0 deletions regressions/ck_rhs/validate/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,39 @@ run_test(unsigned int is, unsigned int ad)
return;
}

static void
test_reset_preallocated(void)
{
ck_rhs_t hs;
size_t size;
void *buffer;
unsigned long h;

if (ck_rhs_init(&hs, CK_RHS_MODE_SPMC | CK_RHS_MODE_OBJECT,
hs_hash, hs_compare, &my_allocator, 16, 6602834) == false) {
ck_error("ck_rhs_init (preallocated)\n");
}

h = test[0][0];
if (ck_rhs_put(&hs, h, test[0]) == false)
ck_error("ck_rhs_put (preallocated)\n");

size = ck_rhs_map_size(&hs, 64);
buffer = hs_malloc(size);
if (buffer == NULL)
ck_error("hs_malloc (preallocated)\n");

ck_rhs_reset_preallocated(&hs, 64, buffer);
if (ck_rhs_count(&hs) != 0)
ck_error("ck_rhs_reset_preallocated failed to clear entries\n");

if (ck_rhs_put(&hs, h, test[0]) == false)
ck_error("ck_rhs_put after ck_rhs_reset_preallocated\n");

ck_rhs_destroy(&hs);
return;
}

int
main(void)
{
Expand All @@ -305,6 +338,7 @@ main(void)
break;
}

test_reset_preallocated();
return 0;
}

66 changes: 55 additions & 11 deletions src/ck_rhs.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,31 +333,44 @@ ck_rhs_destroy(struct ck_rhs *hs)
return;
}

static struct ck_rhs_map *
ck_rhs_map_create(struct ck_rhs *hs, unsigned long entries)
static unsigned long
ck_rhs_map_capacity(unsigned long entries)
{
struct ck_rhs_map *map;
unsigned long size, n_entries, limit;
unsigned long n_entries;

n_entries = ck_internal_power_2(entries);
if (n_entries < CK_RHS_PROBE_L1)
n_entries = CK_RHS_PROBE_L1;

return n_entries;
}

size_t
ck_rhs_map_size(struct ck_rhs *hs, unsigned long entries)
{
unsigned long n_entries;

n_entries = ck_rhs_map_capacity(entries);

if (hs->mode & CK_RHS_MODE_READ_MOSTLY)
size = sizeof(struct ck_rhs_map) +
return sizeof(struct ck_rhs_map) +
(sizeof(void *) * n_entries +
sizeof(struct ck_rhs_no_entry_desc) * n_entries +
2 * CK_MD_CACHELINE - 1);
else
size = sizeof(struct ck_rhs_map) +
return sizeof(struct ck_rhs_map) +
(sizeof(struct ck_rhs_entry_desc) * n_entries +
CK_MD_CACHELINE - 1);
map = hs->m->malloc(size);
if (map == NULL)
return NULL;
map->read_mostly = !!(hs->mode & CK_RHS_MODE_READ_MOSTLY);
}

map->size = size;
static void
ck_rhs_map_init(struct ck_rhs *hs, struct ck_rhs_map *map, unsigned long entries)
{
unsigned long n_entries, limit;

n_entries = ck_rhs_map_capacity(entries);
map->read_mostly = !!(hs->mode & CK_RHS_MODE_READ_MOSTLY);
map->size = ck_rhs_map_size(hs, n_entries);
/* We should probably use a more intelligent heuristic for default probe length. */
limit = ck_internal_max(n_entries >> (CK_RHS_PROBE_L1_SHIFT + 2), CK_RHS_PROBE_L1_DEFAULT);
if (limit > UINT_MAX)
Expand Down Expand Up @@ -394,6 +407,21 @@ ck_rhs_map_create(struct ck_rhs *hs, unsigned long entries)

/* Commit entries purge with respect to map publication. */
ck_pr_fence_store();
return;
}

static struct ck_rhs_map *
ck_rhs_map_create(struct ck_rhs *hs, unsigned long entries)
{
struct ck_rhs_map *map;
size_t size;

size = ck_rhs_map_size(hs, entries);

map = hs->m->malloc(size);
if (map == NULL)
return NULL;
ck_rhs_map_init(hs, map, entries);
return map;
}

Expand Down Expand Up @@ -421,6 +449,22 @@ ck_rhs_reset(struct ck_rhs *hs)
return ck_rhs_reset_size(hs, previous->capacity);
}

void
ck_rhs_reset_preallocated(struct ck_rhs *hs,
unsigned long capacity,
void *memory)
{
struct ck_rhs_map *map, *previous;

previous = hs->map;
map = memory;
ck_rhs_map_init(hs, map, capacity);

ck_pr_store_ptr(&hs->map, map);
ck_rhs_map_destroy(hs->m, previous, true);
return;
}

static inline unsigned long
ck_rhs_map_probe_next(struct ck_rhs_map *map,
unsigned long offset,
Expand Down
Loading