:copyright: Concurrent Programming Library (Coroutine) for C11

libconcurrent

zlib License

tiny asymmetric-coroutine library.

Description

  • asymmetric-coroutine
  • bidirectional communication by yield_value/resume_value
  • native context switch
  • C11

Supported Platforms

x86_64 i686 ARM(v6/v7) note
Linux ✔️ ✔️ ✔️
FreeBSD ✔️ ✔️ Thanks @t6
OSX ✔️ ✖️ ✖️ Thanks @kpamnany

Code Example

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdnoreturn.h>

#include <concurrent/concurrent.h>
#include <concurrent/shortname.h>

#define STACK_SIZE (1024 * 2)


noreturn void accumulator(struct concurrent_ctx *ctx)
{
    int *v = ctx_get_resume_value(ctx);
    int total = *v;
    for (;;) {
        v = yield_value(ctx, &total); // send total / receive next value
        total += *v;
    }
}

int main(void)
{
    struct concurrent_ctx *ctx;
    uint8_t stack[STACK_SIZE];
    uint8_t ctx_alloc[ctx_sizeof()];
    concurrent_init();
    ctx = (struct concurrent_ctx *)ctx_alloc;
    ctx_construct(ctx, stack, STACK_SIZE, accumulator, NULL);
    for (int i = 1; i <= 10; i++) {
        int *total = resume_value(ctx, &i); // send value / receive total
        printf("total = %d\n", *total);
        
    }
    ctx_destruct(ctx);
    concurrent_fin();
    return EXIT_SUCCESS;
}

/*
$ gcc -o sample sample.c -lconcurrent.a
$ ./sample
total = 1
total = 3
total = 6
total = 10
total = 15
total = 21
total = 28
total = 36
total = 45
total = 55
*/

Requirements for build

Installation

$ git clone https://github.com/sharow/libconcurrent.git libconcurrent
$ cd libconcurrent
$ make
$ sudo make install

for FreeBSD

Available in ports collection as devel/libconcurrent

for OSX

$ brew install nasm

Tests

$ make test

Benchmark

examples/many_context1.c:

-- output: (Xeon E3 2.5Ghz)
3000000 context switch in 373.5 ms
one context switch in 125 ns
8031333 resume/yield pair per second


-- output: (RaspberryPi2 ARMv7 900MHz)
3000000 context switch in 2861.8 ms
one context switch in 954 ns
1048287 resume/yield pair per second

VS.

Comments
  • [feature] ARM64 support

    [feature] ARM64 support

    I have finally implemented the ARM64 version. It was lots of fun working with your project on Apple M1. Would you please check whether this version fits the project?

    Thanks

  • new API for detecting Stack Growth and removed mCallerReturnAddress Instruction for ARM.

    new API for detecting Stack Growth and removed mCallerReturnAddress Instruction for ARM.

    :D Based on your tips, i removed these instructions which saves caller Link Register into aContext->mCallerReturnAddress. I thought it was meant for debugging purposes but as you mentioned, we can remove the instructions because lr is saved into stack at L68.

    A new api is added to detect stack growth whether it is downward or upward , by recursion. Here is the algorithm :

    1. Save depth into baseptr as base stack pointer.
    2. Recurs ( pushes previous registers into stack upon entry ) .
    3. Compare baseptr with latest value of { int depth } .
    4. If Stack is descending then (baseptr - depth) must be positive and ( depth + (baseptr - depth ) ) must be equal to baseptr, Otherwise Stack is ascending .

    Thanks

  • Make creating a FreeBSD port smoother

    Make creating a FreeBSD port smoother

    • Add PREFIX option to makefile to allow overriding of install location. Currently installs into /usr whereas on FreeBSD 3rd-party software installs into /usr/local.
    • Don't add -O2 to CFLAGS when on FreeBSD. Optimizations are set by the ports system and can be overridden by users.

    Once this is merged I'll create a FreeBSD port/package and submit it for inclusion in the ports tree.

  • Support OS X

    Support OS X

    Use relative addressing in the assembly code. Remove warning in strsplit example. Add clock_gettime() substitute for time_slice1 example. Don't use uname -o for Darwin in the makefiles. Tested on OS X 10.11.5/Core i7-4770HQ (x86_64) and for regressions on CentOS 7.1/Xeon E5-2699 v4 (x86_64).

    I'd prefer to change the makefiles differently (don't use -o at all, instead use -a and findstring to parse the system name) but this is a more minimal change.

    Edit: closes #9.

  • How to build this library?

    How to build this library?

    In the readme it indicates as being compatible for linux and windows. However, it is not clear how to achieve this on windows.

    Could you please provide instructions on how to build on windows with MSVC and how to setup a simple sample?

    If possible, a CMake build system could be very useful for this kind of cross-platform library.

    Thank you.

  • Remove explicitly set CC and LD on FreeBSD

    Remove explicitly set CC and LD on FreeBSD

    libconcurrent is now in the ports tree: https://www.freshports.org/devel/libconcurrent

    There was some fallout from the package build on FreeBSD 9. With the recent changes to the makefile we don't need to set CC and LD anymore on FreeBSD. The problem is that this prevents setting of the correct compiler on FreeBSD 9. I've just updated the port to remove those lines but it would be great if this can be merged :)

  • error compile on mac

    error compile on mac

    ➜  libconcurrent git:(master) make   
    uname: illegal option -- o
    usage: uname [-amnprsv]
    uname: illegal option -- o
    usage: uname [-amnprsv]
    uname: illegal option -- o
    usage: uname [-amnprsv]
    uname: illegal option -- o
    usage: uname [-amnprsv]
    nasm  -f elf64 src/arch/x86_64/concurrent_arch.asm -o src/arch/x86_64/concurrent_arch.o
    nasm: fatal: unrecognised output format `elf64' - use -hf for a list
    type `nasm -h' for help
    make: *** [src/arch/x86_64/concurrent_arch.o] Error 1
    
  • Removed mCallerReturnAddress Instructions.

    Removed mCallerReturnAddress Instructions.

    :D Based on your tips, i removed these instructions which saves caller Link Register into aContext->mCallerReturnAddress. I thought it was meant for debugging purposes but as you mentioned, we can remove the instructions because lr is saved into stack at L68. Thanks

  • Corrected code comments.

    Corrected code comments.

    Corrected small error in code documentation.

    str lr, [r0, r2]. In this case, address of link register is stored at mCallerReturnAddress not lr = mCallerReturnAddress.

  • stack: fix possible stack buffer overflow

    stack: fix possible stack buffer overflow

    Oups, I just blindly updated the old code and didn't realized that if stack size is multiple of 16, but the stack is not aligned, only the stack beginning is corrected, not it's size. Thus the first push into the stack will overflow the buffer.

  • Stack alignment + some random fixes

    Stack alignment + some random fixes

    There are some fixes I made while I was trying to use libconcurrent. I didn't want to create a pull request for each one, you can cherry-pick specific commits if you don't like all of these.

    cbdb5b0 removed executable bit from non executable files 8efb89c this one took me a while to figure out. Some glibc/libstdc++ functions use xmm registers on x86_64, but it will segfault if it tries to push/save an xmm register to the stack if it's only 8 byte aligned. They're 128bit registers, so they need 16 byte alignment. 1fcf974 added missing .gitignore f21f9f3 stripping the static library gives libconcurrent.a: error adding symbols: Archive has no index; run ranlib to add one when I try to later link it with a command.

Coroutine - C++11 single .h asymmetric coroutine implementation via ucontext / fiber

C++11 single .h asymmetric coroutine implementation API in namespace coroutine: routine_t create(std::function<void()> f); void destroy(routine_t id);

Nov 16, 2022
A C++ library of Concurrent Data Structures

CDS C++ library The Concurrent Data Structures (CDS) library is a collection of concurrent containers that don't require external (manual) synchroniza

Dec 1, 2022
A C++ library providing various concurrent data structures and reclamation schemes.

xenium xenium is a header-only library that provides a collection of concurrent data structures and memory reclamation algorithms. The data structures

Nov 25, 2022
Single header asymmetric stackful cross-platform coroutine library in pure C.
Single header asymmetric stackful cross-platform coroutine library in pure C.

minicoro Minicoro is single-file library for using asymmetric coroutines in C. The API is inspired by Lua coroutines but with C use in mind. The proje

Nov 30, 2022
A golang-style C++ coroutine library and more.

CO is an elegant and efficient C++ base library that supports Linux, Windows and Mac platforms. It pursues minimalism and efficiency, and does not rely on third-party library such as boost.

Dec 4, 2022
A C++20 coroutine library based off asyncio
A C++20 coroutine library based off asyncio

kuro A C++20 coroutine library, somewhat modelled on Python's asyncio Requirements Kuro requires a C++20 compliant compiler and a Linux OS. Tested on

Nov 9, 2022
C++20 Coroutine-Based Synchronous Parser Combinator Library

This library contains a monadic parser type and associated combinators that can be composed to create parsers using C++20 Coroutines.

Oct 13, 2022
Cppcoro - A library of C++ coroutine abstractions for the coroutines TS

CppCoro - A coroutine library for C++ The 'cppcoro' library provides a large set of general-purpose primitives for making use of the coroutines TS pro

Nov 29, 2022
A go-style coroutine library in C++11 and more.
A go-style coroutine library in C++11 and more.

cocoyaxi English | 简体中文 A go-style coroutine library in C++11 and more. 0. Introduction cocoyaxi (co for short), is an elegant and efficient cross-pla

Dec 2, 2022
C++14 coroutine-based task library for games

SquidTasks Squid::Tasks is a header-only C++14 coroutine-based task library for games. Full project and source code available at https://github.com/we

Nov 30, 2022
Nov 30, 2022
A fast multi-producer, multi-consumer lock-free concurrent queue for C++11

moodycamel::ConcurrentQueue An industrial-strength lock-free queue for C++. Note: If all you need is a single-producer, single-consumer queue, I have

Dec 1, 2022
Concurrent data structures in C++
Concurrent data structures in C++

Junction is a library of concurrent data structures in C++. It contains several hash map implementations: junction::ConcurrentMap_Crude junction::Conc

Nov 29, 2022
A bounded multi-producer multi-consumer concurrent queue written in C++11
A bounded multi-producer multi-consumer concurrent queue written in C++11

MPMCQueue.h A bounded multi-producer multi-consumer concurrent queue written in C++11. It's battle hardened and used daily in production: In the Frost

Nov 25, 2022
Powerful multi-threaded coroutine dispatcher and parallel execution engine

Quantum Library : A scalable C++ coroutine framework Quantum is a full-featured and powerful C++ framework build on top of the Boost coroutine library

Nov 28, 2022
Async GRPC with C++20 coroutine support

agrpc Build an elegant GRPC async interface with C++20 coroutine and libunifex (target for C++23 executor). Get started mkdir build && cd build conan

Nov 15, 2022
Mx - C++ coroutine await, yield, channels, i/o events (single header + link to boost)

mx C++11 coroutine await, yield, channels, i/o events (single header + link to boost). This was originally part of my c++ util library kit, but I'm se

Sep 21, 2019
Elle - The Elle coroutine-based asynchronous C++ development framework.
Elle - The Elle coroutine-based asynchronous C++ development framework.

Elle, the coroutine-based asynchronous C++ development framework Elle is a collection of libraries, written in modern C++ (C++14). It contains a rich

Nov 19, 2022
Kokkos C++ Performance Portability Programming EcoSystem: The Programming Model - Parallel Execution and Memory Abstraction

Kokkos: Core Libraries Kokkos Core implements a programming model in C++ for writing performance portable applications targeting all major HPC platfor

Nov 27, 2022