# FYI: C++20 std:jthread vs Julia's threads

**URL:** https://discourse.julialang.org/t/fyi-c-20-std-jthread-vs-julias-threads/116502
**Category:** Offtopic
**Created:** [July 2, 2024, 3:45am UTC](https://discourse.julialang.org/t/fyi-c-20-std-jthread-vs-julias-threads/116502 "2024-07-02T03:45:17Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [July 2, 2024, 3:45am UTC](https://discourse.julialang.org/t/fyi-c-20-std-jthread-vs-julias-threads/116502/1 "2024-07-02T03:45:17Z")

</div>

[![](https://global.discourse-cdn.com/julialang/original/3X/a/2/a21e85886b2ca14d932e80e8c909c699bc6e3ee3.jpeg "std::jthread - I Told You Concurrency Is Tricky - Nico Josuttis [ACCU 2021]") ](https://www.youtube.com/watch?v=ln5ERAVXEMY)

I notices Julia’s GC relies on C++ code. I though the GC was written in C, and only the LLVM and parts related to it written in C++, but at least by now Julia’s GC relies on C++11, i.e. on std:thread. All threads seemingly rely on it (if I recall from C++11), and since the GC is now multi-threaded it too.

Then I got curious and looked into threads in C++, and since this jthread is rather new wrapper on thread, I’m curious what people did before C++20, how much better this new thing is, people use boost or something? Same for C people, what do they do? Should Julia’s threads rely on std::jthread (would it be a simple change… adding j?), thus C++20, not just/mostly for the GC (actually if might not need it…).

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [July 2, 2024, 6:09am UTC](https://discourse.julialang.org/t/fyi-c-20-std-jthread-vs-julias-threads/116502/2 "2024-07-02T06:09:41Z")

</div>

In C one simply used pthreads directly. I’ve written a couple of threaded R-packages. R did not support threading (due in part to reliance on addressing relative to the base of the stack), so it had to be completely hidden in C/C++. So it was pthreads, but ifdef’ed for native threads on windows. It’s not very hard. You just write a function to run in the thread, and launch it with pthread\_create.

---

<div class="post-metadata">

### Author: ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)
#### Post date: [July 2, 2024, 12:32pm UTC](https://discourse.julialang.org/t/fyi-c-20-std-jthread-vs-julias-threads/116502/3 "2024-07-02T12:32:43Z")

</div>

> [@Palli](#):
>
> I though the GC was written in C, and only the LLVM and parts related to it written in C++, but at least by now Julia’s GC relies on C++11, i.e. on std:thread. All threads seemingly rely on it (if I recall from C++11), and since the GC is now multi-threaded it too.

The GC is still written in C and we don’t use `std::thread` we use LibUV as a shallow portability layer over pthreads

---

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [July 2, 2024, 4:21pm UTC](https://discourse.julialang.org/t/fyi-c-20-std-jthread-vs-julias-threads/116502/4 "2024-07-02T16:21:59Z")

</div>

> [@vchuravy](#):
>
> The GC is still written in C and we don’t use `std::thread`

TL;DR Thanks for [un]clarifying. I believe we’re on the same page, the GC is “C” code, as I thought and still think, only depending on C++ code; thus requiring a C++ compiler (so in some strict technical sense C++ code\*), what I had in mind with it “being” C++ code (i.e. it, e.g. gc.c is C code, non-OOP, only depends on templated C++ code, `jl_atomic_*` functions). [I assume I was incorrectly implicating std::threads (for the GC or any Julia code) as opposed to C++ std::atomic\_fetch\_add. Both are concurrency-related, so linked in my mind.]

It all started with me looking at this, and pros and cons of that new merged PR vs old code (it’s faster, I believe no, or less(?), possible lock contention; for lines excluding 1541, that changed line is still unclear to me) and how the GC is implemented:

> <https://github.com/JuliaLang/julia/pull/54976/files>

I believe julia\_atomics.h is a C++ file (a so-called header-only file, if it’s not C++ then all my argument falls apart, see below\*), and thus all code, any .c (not just .cpp) files, that depends on it, are in effect C++ code, requiring a C++ compiler.\*

Files such as: ccall.cpp (and iddict.c, engine.cpp, julia\_atomics.h, smallintset.c precompileutils.c).

I.e. it came as a surprise to me that when you use the `ccall` keyword, to call C code (not e.g. C++, Fortran or Rust), then C++ is still involved, i.e. ccall.cpp; and atomics (why?).

julia\_threads.h depends on julia\_atomics.h, and yes pthread.h (except on Windows).

I can’t clearly see that std::thread is actually used (probably isn’t), was a wrong assumption on my part, just based on seeing C++ atomics.

My question still remains, what are the pros and cons for using C++11 std::threads (for Julia) vs C++20 std::jthreads vs pthread.h (or something equivalent on Windows).

I’m not trying to argue, just clarify for myself (and others). Everything you can do in C++, C++11 (or C++20) you can do in C, in some equivalent way, at least for atomics (I’m thinking semantics, not arguing pros and cons of C++ vs C for code maintenance).

`*` Is code requiring a C++ compiler C++ code? If it’s C code depending on C++ code (not dynamically linked). C++ is a (non-strict) superset of C, so most C code can be called C++ code. It may be unfair if it’s actually only (non-OOP) C code. If Julia code depends on e.g. C or C++ code, then we do not call it C/C++ code, just because the code depends on a JLL, but we (at least I) do not call it `pure Julia` code. That has never been a huge concern of mine, we _should_ depend on good available (at least proven correct, e.g. Rust) libraries regardless of language.

julia\_atomics.h is actually conditionally compiled

> <https://github.com/JuliaLang/julia/blob/f2558c461c85be4220901f4c67cbce718ddc015b/src/julia_atomics.h#L11-L13>

…

> <https://github.com/JuliaLang/julia/blob/f2558c461c85be4220901f4c67cbce718ddc015b/src/julia_atomics.h#L37-L39>

so what does it actually mean, is it also compiled by a C compiler? I.e. triggering lines 37 and 38, such as for the GC? Then that seems to be an implementation detail, I still see:

> <https://github.com/JuliaLang/julia/blob/f2558c461c85be4220901f4c67cbce718ddc015b/src/julia_atomics.h#L129-L139>

> <https://github.com/JuliaLang/julia/blob/f2558c461c85be4220901f4c67cbce718ddc015b/src/julia_atomics.h#L123-L127>

---

<div class="post-metadata">

### Author: ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)
#### Post date: [July 2, 2024, 5:05pm UTC](https://discourse.julialang.org/t/fyi-c-20-std-jthread-vs-julias-threads/116502/5 "2024-07-02T17:05:07Z")

</div>

> [@Palli](#):
>
> I believe julia\_atomics.h is a C++ file (a so-called header-only file,

`julia_atomics.h` is a polymorph, it provides functionality for both C and C++ components.

If it is included from C++ it’s uses different code paths [julia/src/julia\_atomics.h at f2558c461c85be4220901f4c67cbce718ddc015b · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/f2558c461c85be4220901f4c67cbce718ddc015b/src/julia_atomics.h#L11)

Every file that uses `.c` is compiled with a C compiler:

> <https://github.com/JuliaLang/julia/blob/f2558c461c85be4220901f4c67cbce718ddc015b/src/Makefile#L238>

We are using `stdatomic` because the C/C++ memory model is pretty great.

We are not using `std::threads` since it doesn’t really help us as a layer of abstraction over OS threads.

We use LibUV for threads.
