Giter Club home page Giter Club logo

c11threads's Introduction

Trivial C11 threads.h implementation over POSIX threads, and not-so-trivial implementation over Win32 threads.

Rationale

Even though GCC provides the threading features required by the C11 standard (like atomics, and thread-local storage), GNU libc, still does not implement the necessary library functions of the standard C thread API. Other popular platforms similarly lack support for the C11 thread functions, like Microsoft's C runtime library on Windows.

If you're starting a new multithreaded project in C right now, it would make sense to use the standard C way of using threads instead of a mishmash of various platform-specific APIs. So until the system libc adds support for it, we need a stopgap that works exactly as the C standard describes.

License

Authors:

I place this piece of code in the public domain. Feel free to use as you see fit. I'd appreciate it if you keep my name at the top of the code somewhere, but whatever.

How to use

With POSIX threads

On UNIX systems, or on Windows with a 3rd party pthreads library, c11threads is implemented as a thin wrapper of static inline functions over pthreads.

No installation or compilation necessary; just drop c11threads.h into your project source tree, and don't forget to link with -lpthread. On some platforms it might be required to also pass the -pthread flag to the compiler.

If your compiler does not support the inline keyword, define C11THREADS_INLINE to whatever equivalent keyword the compiler provides, or to the empty string to make all the functions simply static.

If you wish to use the pthreads implementation on Windows, in preference to the native win32 one, you need to define C11THREADS_PTHREAD_WIN32.

With Win32 threads

To use C11 threads over the Windows threads API, beyond adding c11threads.h to your project, you also need to compile c11threads_win32.c as part of your build. Additionally, if you're in a situation where letting c11threads keep resources for the duration of the process lifetime is not desirable, you can call c11threads_destroy_win32() to free them manually at any point, when you're done with it.

Test program

There's a simple test program under test/. To build it on UNIX (GNU/Linux, FreeBSD, MacOSX, whatever), simply change into the test directory and type make.

To build the test program on Windows with MSVC using native win32 threads, setup the build environment (usually there's a batch file called vcvars*.bat, run it in a console), and use microsoft nmake to build: nmake -f Makefile.msvc.

Contact

Main project site: https://github.com/jtsiomb/c11threads

Feel free to send corrections, patches, trendy social pull requests, pictures of your cat wearing santa hats, any good porn links, or investment opportunities with Nigerian ex-royals... It's all good.

c11threads's People

Contributors

aeckar avatar gjmvervoort avatar horta avatar jtsiomb avatar luiji avatar oold avatar schaten avatar twistdroach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

c11threads's Issues

Trap deadlocks

In mtx_lock(), I think you should trap the dead-lock with an assert:

if(res == EDEADLK) {
    assert(false);  // Dead-locks are undefined behaviour
    return thrd_busy;
}

According to the C11 standard, a dead-lock is undefined behaviour. However, with POSIX threads, the behaviour is well defined. What we want to avoid is client code silently discarding dead-locks, by calling mtx_lock(), without paying attention to the return value, which turns into a no-op. Instead code should crash, at least in debug compiles, so programmers can see that they are relying on a deadlock (which is undefined).

What do you think ?

CI

Would be nice to see some CI here, one good option might be https://travis-ci.org - really easy to integrate, especially for project like this.

Test failure on FreeBSD

Hello.

This is actually about C11 threads on FreeBSD 13.2, using native C11 threads. What I mean is building the test but including real "threads.h" instead of "c11threads.h" and linking with "-lstdthreads", instead of "-lthr" (which is "-lpthread" on FreeBSD systems).

I'd expect the test to function identically. It does on (at least) AIX and Linux/glibc and Linux/musl.

The problem is on FreeBSD, using the real system C11 threads library, results in the following failure:

test.c:249: thrd_sleep(&dur, ((void *)0)): error 0, expected thrd_success

It all works as expected using the test with c11threads.h.

Windows threads support

Would be really nice to see win threads support here! I might do it because I'm quite desperate looking for C-only cross-platform threading lib.

gcc timespec_get build error

Description: gcc build error "c11threads.h:LINE: error: static declaration of 'timespec_get' follows non-static declaration
static inline int timespec_get(struct timespec *ts, int base)"
Possible cause: #7 PTHREAD_MUTEX_TIMED_NP is not available outside of Linux
Specs: gcc version 5.4.0, on Ubuntu 16.04.2 LTS
STDC_VERSION = 201112L

More info:
At the beginning of c11threads.h PTHREAD_MUTEX_TIMED_NP is checked, and if not found timespec_get will be defined at the bottom of the header. pthread.h declares the timespec_get function, and defines PTHREAD_MUTEX_TIMED_NP as an enum value, and not a macro.

Duplicated declaration of timespec_get() on MacOSX

Got this error:

c11threads.h:262:19: error: static declaration of 'timespec_get' follows non-static declaration
static inline int timespec_get(struct timespec *ts, int base)
                  ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/usr/include/time.h:199:5: note: previous declaration is here
int timespec_get(struct timespec *ts, int base);

Temporarily worked around it by changing:

#if __STDC_VERSION__ < 201112L || defined(C11THREADS_NO_TIMED_MUTEX)
/* TODO take base into account */
static inline int timespec_get(struct timespec *ts, int base)

to

#if __STDC_VERSION__ < 201112L
/* TODO take base into account */
static inline int timespec_get(struct timespec *ts, int base)

Didn't really dig to see what the "proper" fix is, but I suspect timespec_get() was added in a new version of the MacOSX SDK?

warning: cast to pointer from integer

When compiling on MinGW I get these warnings:

c11threads.h: In function 'thrd_exit':
c11threads.h:70:15: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   70 |  pthread_exit((void*)(long)res);
      |               ^
c11threads.h: In function 'thrd_join':
c11threads.h:81:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   81 |   *res = (int)(long)retval;
      |               ^

That's because long is 32 bit on this platform. The ideal solution would be to replace it with intptr_t but it is only (optionally) available since c99.
Maybe using long long when __MINGW64__ is defined will do.

error: weak declaration of 'thrd_exit' must be public

When building grep 3.8 I see this issue. (I've saved c11threads.h to /usr/local/include/threads.h on a i686 glibc 2.23 system.)

In file included from ./glthread/lock.h:87,
                 from glthread/lock.c:22:
/usr/local/include/threads.h:69:20: error: weak declaration of 'thrd_exit' must be public
   69 | static inline void thrd_exit(int res)
      |                    ^~~~~~~~~
make[3]: *** [Makefile:3661: glthread/libgreputils_a-lock.o] Error 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.