Open-source project
concurrencykit/ck avatar
concurrencykit/ck

Concurrency Kit (ck): C99 concurrency primitives, safe memory reclamation and lock-free data structures

Concurrency primitives, safe memory reclamation mechanisms and non-blocking (including lock-free) data structures designed to aid in the research, design and implementation of high performance concurrent systems developed in C99+.

2,704 stars336 forksCNOASSERTION

At a glance

What is it?
Concurrency Kit is a C99 library of atomic primitives, epoch and hazard-pointer reclamation, and lock-free containers, built for people writing their own concurrent data structures rather than calling an existing thread pool. It installs from a configure and make, and its licence file is not a standard SPDX identifier.
Who is it for?
Adopt ck if you are writing a concurrent data structure or a lock-free container in C and want tested primitives, epoch or hazard-pointer reclamation, and reference implementations to compare against. Do not adopt it if you want a task scheduler, a thread pool or a C++ API: the repository is C99 headers and sources, and the README lists no such components.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Concurrency Kit solves, and who it is written for

Concurrency Kit is not a threading library. It does not schedule work, own a thread pool, or give you futures. What it provides is the layer underneath: the atomic operations, the memory reclamation schemes, and the containers that a concurrent system is assembled from. The README frames the project as primitives and building blocks "designed to aid in the research, design and implementation of high performance concurrent systems developed in C99+".

The audience follows from that. If you are writing a lock-free queue, a read-mostly hash table, or a reclamation scheme of your own, ck supplies both the parts and the reference implementations to compare against. If you are writing an application that needs a background worker, ck is the wrong level of abstraction. The repository layout reflects the same intent: include/, src/, regressions/ and doc/ sit alongside tools/ and a configure script, which is the shape of a library meant to be linked into other people's code, not a framework that owns your program.

How ck is organised: primitives, reclamation, containers, locks

The README groups the library into four families. Concurrency primitives cover ck_pr (atomic operations, with wrappers around CAS where native support is missing, plus RTM, pipeline control and read-for-ownership), ck_backoff, and ck_cc, which abstracts compiler builtins for people writing their own structures. Safe memory reclamation covers ck_epoch, described as a scalable reclamation mechanism with support for idle threads, and ck_hp, an implementation of hazard pointers.

Data structures include ck_array, ck_bitmap, ck_ring, ck_fifo, ck_hp_fifo, ck_hp_stack, ck_stack, ck_queue, ck_hs, ck_ht and ck_rhs. Two design notes in that list matter more than the rest. ck_hs is described as a single-writer-many-reader hash set that satisfies lock-freedom with bounded concurrency "without any usage of atomic operations", and the README recommends it as a general hash set when values can be computed from keys. ck_ht is the specialisation that allows disjunct key-value pairs, and ck_rhs applies robin-hood hashing for higher load factors and high deletion rates.

The fourth family is synchronisation: ck_ec (an event counter presented as an alternative to condition variables), ck_barrier with centralised, combining, dissemination, MCS and tournament variants, ck_brlock, ck_bytelock, ck_cohort, ck_elide, ck_pflock, ck_rwcohort, ck_rwlock, ck_sequence, ck_swlock, ck_tflock and several spinlocks. Two entries are explicitly labelled as research or reference material rather than production defaults: ck_bytelock, where the README notes that in reality memory barriers are required on the fast path, and ck_spinlock_dec, "primarily here for reference". The cohorting interfaces come with a stated cost: a significant trade-off in fast path acquisition cost in exchange for NUMA scalability.

Installing Concurrency Kit and building the regressions

The README gives a three-step build. First run the configure script from the repository root; additional options are listed by passing --help. Then choose what to build: make regressions compiles the regression suite and requires POSIX threads, while make all or plain make builds libck. Finally make install installs it, and make uninstall removes it.

bash
./configure
./configure --help
make regressions
make all
make install

A first real use is to build the regressions and run them, because that exercises the primitives and data structures against your compiler and architecture before you depend on them. The Makefile.in at the repository root is the template the configure script fills in, so if the default build flags do not match your target you are expected to adjust them there rather than patch generated files.

bash
make regressions

The README does not document a pkg-config file, a CMake package or a Meson wrap, so linking against libck means pointing your compiler and linker at the installed prefix yourself. It also does not document rollback or version pinning beyond the tagged releases.

Where the portability story gets thin

Concurrency Kit supports any architecture through compiler built-ins as a fallback, and the README is direct that "there is usually a performance degradation associated with this". Specialised assembly exists for aarch64, arm, ppc, ppc64, riscv64, s390x, sparcv9+, x86 and x86_64. That list is the real portability boundary. On anything outside it you get a correct build with a performance profile you have not measured, which is a poor trade for a library whose whole premise is speed.

Continuous integration is narrower still. The README lists five targets: darwin/clang/arm64, freebsd/clang/x86-64, linux/gcc/arm64, linux/gcc/x86-64 and linux/clang/x86-64. Windows appears only in the historical compiler list (cygwin, mingw32, mingw64), not in the current CI matrix, so a Windows build is plausible but not continuously verified. The README also states that all new architectures are required to pass the integration test and undergo extensive code review, which tells you the maintainers treat architecture ports as a gated change rather than a casual contribution.

The release cadence is another constraint worth naming. The most recent release is 0.7.2 from 2024-03-24, preceded by 0.7.1 in 2021 and 0.7.0 in 2019. The repository's last push was on 2026-09-23, so work continues between releases, but if you depend on tagged versions you are working with something that moves on a multi-year rhythm. Pin a tag and expect to carry local patches if you need a fix that only exists on master.

Choosing between ck_epoch and ck_hp, and when neither fits

The two reclamation mechanisms solve the same problem with different costs. ck_epoch is presented as a scalable mechanism with support for idle threads; ck_hp implements hazard pointers, described as a simple and efficient lock-free scheme. The practical difference is in the read path. Epoch-based reclamation defers freeing until no thread is inside a critical section, which keeps the common case cheap but makes the reclamation latency depend on the slowest participant, and idle threads are exactly the case the README calls out as needing support. Hazard pointers make each reader publish the pointers it is using, so reclamation is bounded, at the cost of a store and a memory barrier per protected access.

If your readers are short and uniform, epoch is the easier fit. If a single stalled thread must not hold back memory, hazard pointers are the safer choice, and the ck_hp_fifo and ck_hp_stack implementations show how they are meant to be wired into a container. Neither mechanism helps if your problem is not reclamation. If you are protecting a large structure with mostly writes, a plain lock from the synchronisation section will be faster to reason about than a lock-free rewrite, and ck_rwlock or ck_pflock exist for that case. The README itself points at ck_sequence for structures where deep copy is permitted, which is a much smaller change than converting a container to lock-free.

Concurrency Kit compared with a general-purpose threading library

The obvious alternative is a general-purpose concurrency runtime: oneTBB, or the threading facilities in a language runtime, or simply pthreads plus a lock. The difference is one of level. A threading library gives you threads, mutexes and condition variables, and stops there; it assumes your data structures are protected by locks. Concurrency Kit gives you the atomic layer, the reclamation schemes and the containers, and assumes you are building the data structure yourself.

That shows up in the components. ck_ec is offered as an alternative to condition variables, with specialisation for fixed concurrency use-cases, which is a narrower and faster contract than a general condition variable. ck_cohort and ck_rwcohort take any lock and make it NUMA-friendly, with an explicit trade-off in fast path acquisition cost; a general-purpose runtime would make that decision for you or not offer it. And ck_hs is a single-writer-many-reader hash set that the README says uses no atomic operations, which is a design point a general container library would not reach for. If your workload is single-writer, many-reader, that is a concrete reason to pick ck over a lock-protected map.

The cost of that level is that you own correctness. ck gives you reference implementations and a regression suite, not a guarantee that your use of them is right.

Editorial conclusion

Adopt ck if you are writing a concurrent data structure or a lock-free container in C and want tested primitives, epoch or hazard-pointer reclamation, and reference implementations to compare against. Do not adopt it if you want a task scheduler, a thread pool or a C++ API: the repository is C99 headers and sources, and the README lists no such components. Before committing, check LICENSE because GitHub reports NOASSERTION rather than a recognised identifier, and confirm that the architectures you ship on are among the ones with specialised assembly.

Frequently asked questions

How do I install Concurrency Kit (ck)?

Run ./configure from the repository root, then make all (or make) to build libck, and make install to install it. make regressions compiles the regression suite and requires POSIX threads.

Which architectures does Concurrency Kit have specialised assembly for?

The README lists aarch64, arm, ppc, ppc64, riscv64, s390x, sparcv9+, x86 and x86_64. Any other architecture falls back to compiler built-ins, which the README says usually carries a performance degradation.

What is the difference between ck_epoch and ck_hp in Concurrency Kit?

ck_epoch is a scalable safe memory reclamation mechanism with support for idle threads, while ck_hp implements hazard pointers, described as a simple and efficient lock-free reclamation mechanism. The README presents them as two options for the same problem rather than one replacing the other.

What licence is Concurrency Kit released under?

The repository contains a LICENSE file, but GitHub reports the licence as NOASSERTION, meaning it could not be matched to a recognised identifier. Read that file directly before you rely on it.

Official sources

  1. concurrencykit/ck on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/concurrencykit-ck.svg)](https://hysenlabs.com/projects/concurrencykit-ck)