digitalmars.D - Unused druntime code: Barrier, ReadWriteMutex, Condition
- Denis Feklushkin (13/13) Jun 14 While working on FreeRTOS support several years ago I discovered
- Richard (Rikki) Andrew Cattermole (10/26) Jun 15 Here is a "standard" addon that gets mentioned for FreeRTOS for read
- Denis Feklushkin (14/18) Jun 15 Strictly, my question wasn't related to FreeRTOS.
- Richard (Rikki) Andrew Cattermole (7/30) Jun 15 They do.
- Denis Feklushkin (4/15) Jun 15 A cool take for an online debate in 2026 :-)
- Denis Feklushkin (4/8) Jun 15 It is possible make PR on this base which will satisfy everyone.
- Denis Feklushkin (6/14) Jun 15 The attempt to use standard Semaphore and Mutex in ondition
- Richard (Rikki) Andrew Cattermole (5/21) Jun 15 The implementation can be extracted into a package struct.
- Denis Feklushkin (11/21) Jun 16 This leads to duplication of code what already available in
- Richard (Rikki) Andrew Cattermole (22/40) Jun 16 No.
- Denis Feklushkin (10/13) Jun 16 By the way, this is off-topic, I have one more suggestion on this
- Richard (Rikki) Andrew Cattermole (5/25) Jun 16 Chuck it into a module called core.internal.platform and sure.
- Denis Feklushkin (6/17) Jun 16 Yes, maybe aliases. Point is in restrictions for druntime
- Richard (Rikki) Andrew Cattermole (4/25) Jun 16 Yeah its a known issue with druntime when it comes to porting it.
- Denis Feklushkin (14/28) Jun 16 Condition class currently isn't cross-platform. Making it so is a
- Dejan Lekic (11/13) Jun 16 Why not do what we typically did in the past - mark it deprecated
- Richard (Rikki) Andrew Cattermole (7/21) Jun 16 1. It would need to be more like 6 years, not 6 months with such long
- Serg Gini (5/6) Jun 16 This is all good, but could you clearly specify the path for
- Richard (Rikki) Andrew Cattermole (7/14) Jun 16 I have given two good options to handle these two classes.
- Denis Feklushkin (8/9) Jun 16 Why? Because someone 20 years ago, apparently by accident,
- Richard (Rikki) Andrew Cattermole (15/27) Jun 16 So version it off like we do with bindings.
- Denis Feklushkin (4/10) Jun 16 But this will break existing code which using Barrier when
- Richard (Rikki) Andrew Cattermole (4/18) Jun 16 Nobody is compiling for FreeRTOS using upstream druntime if it hasn't
- Denis Feklushkin (38/41) Jun 16 I claim that this is accidentally added code that has been used
- Denis Feklushkin (4/7) Jun 16 (The train of thought suddenly stopped)
- Denis Feklushkin (4/10) Jun 16 But this will break existing code which using Barrier when
- Nick Treleaven (6/14) Jun 17 `@disable` doesn't work with types. You can do `@disable new();`
- Richard (Rikki) Andrew Cattermole (2/19) Jun 17 That should really be fixed to make @disable work on types.
- Nick Treleaven (3/14) Jun 20 Filed issue & PR:
- Walter Bright (3/3) Jun 15 Thank you for your work supporting FreeRTOS!
- Denis Feklushkin (22/25) Jun 15 In dmd repository first commit containing mentioned above classes
While working on FreeRTOS support several years ago I discovered that druntime's classes Barrier, ReadWriteMutex and Condition weren't used at druntime or by compiler (CI with mentioned classes disabled https://github.com/dlang/dmd/pull/23265) In fact, Barrier and ReadWriteMutex aren't used at all in any std D libraries or by compiler and Condition is used only in Phobos. They all rely on Condition. The problem with it is that Condition uses primitive provided by the OS (pthread_condattr if Posix). However, not all operating systems provide this primitive (FreeRTOS for example) and this causes a problem out of nowhere. Since this code is not necessary for Dlang's core functionality, I propose moving all mentioned classes to Phobos with appropriate warning messages
Jun 14
On 15/06/2026 9:36 AM, Denis Feklushkin wrote:While working on FreeRTOS support several years ago I discovered that druntime's classes Barrier, ReadWriteMutex and Condition weren't used at druntime or by compiler (CI with mentioned classes disabled https:// github.com/dlang/dmd/pull/23265) In fact, Barrier and ReadWriteMutex aren't used at all in any std D libraries or by compiler and Condition is used only in Phobos. They all rely on Condition. The problem with it is that Condition uses primitive provided by the OS (pthread_condattr if Posix). However, not all operating systems provide this primitive (FreeRTOS for example) and this causes a problem out of nowhere. Since this code is not necessary for Dlang's core functionality, I propose moving all mentioned classes to Phobos with appropriate warning messagesHere is a "standard" addon that gets mentioned for FreeRTOS for read write mutex: https://github.com/michaelbecker/freertos-addons/blob/master/c/Source/read_write_lock.c Condition: https://github.com/michaelbecker/freertos-addons/blob/master/c%2B%2B/Source/ccondition_variable.cpp There are enough primitives in FreeRTOS to build these other sync primitives. If you don't want to implement these two types, feel free to version it off. Let's not go breaking existing code bases.
Jun 15
On Monday, 15 June 2026 at 09:07:54 UTC, Richard (Rikki) Andrew Cattermole wrote:There are enough primitives in FreeRTOS to build these other sync primitives.Strictly, my question wasn't related to FreeRTOS. I just want to understand why we keep such code that we don't use directly in the druntime. This code complicates porting without providing any benefit. Moving this code to Phobos allows us to put this issue aside along with other similar ones (like std.file on systems without filesystem) One day we'll have to quickly port the language to something trendy. And we won't be ready for it.There are enough primitives in FreeRTOS to build these other sync primitives.Most likely, these primitives do not exist in any OS - they are too high-level and can be implemented on the basis of "more primitive" primitives. (Posix implementation just provides convient wrapper, I think)
Jun 15
On 15/06/2026 9:41 PM, Denis Feklushkin wrote:On Monday, 15 June 2026 at 09:07:54 UTC, Richard (Rikki) Andrew Cattermole wrote:They do. Windows Internals 7th edition, part 2. Page 205-206. Reasoning mentioned is that it has performance benefits. Its safe to assume some pthread implementations will have kernel backing as well.There are enough primitives in FreeRTOS to build these other sync primitives.Strictly, my question wasn't related to FreeRTOS. I just want to understand why we keep such code that we don't use directly in the druntime. This code complicates porting without providing any benefit. Moving this code to Phobos allows us to put this issue aside along with other similar ones (like std.file on systems without filesystem) One day we'll have to quickly port the language to something trendy. And we won't be ready for it.There are enough primitives in FreeRTOS to build these other sync primitives.Most likely, these primitives do not exist in any OS - they are too high-level and can be implemented on the basis of "more primitive" primitives. (Posix implementation just provides convient wrapper, I think)
Jun 15
On Monday, 15 June 2026 at 09:59:06 UTC, Richard (Rikki) Andrew Cattermole wrote:A cool take for an online debate in 2026 :-)They do. Windows Internals 7th edition, part 2. Page 205-206.There are enough primitives in FreeRTOS to build these other sync primitives.Most likely, these primitives do not exist in any OS - they are too high-level and can be implemented on the basis of "more primitive" primitives. (Posix implementation just provides convient wrapper, I think)Reasoning mentioned is that it has performance benefits.Luckily, druntime don't use it for Windows
Jun 15
On Monday, 15 June 2026 at 09:41:00 UTC, Denis Feklushkin wrote:Most likely, these primitives do not exist in any OS - they are too high-level and can be implemented on the basis of "more primitive" primitives. (Posix implementation just provides convient wrapper, I think)It is possible make PR on this base which will satisfy everyone. However, I'll wait for information about Windows (see previous message).
Jun 15
On Monday, 15 June 2026 at 10:35:39 UTC, Denis Feklushkin wrote:On Monday, 15 June 2026 at 09:41:00 UTC, Denis Feklushkin wrote:The attempt to use standard Semaphore and Mutex in ondition implementation failed because the current Condition semantics requires nogc, but Mutex and Semaphore are classes and std.typecons.scoped isn't available in druntime. This is another argument for moving this code to PhobosMost likely, these primitives do not exist in any OS - they are too high-level and can be implemented on the basis of "more primitive" primitives. (Posix implementation just provides convient wrapper, I think)It is possible make PR on this base which will satisfy everyone. However, I'll wait for information about Windows (see previous message).
Jun 15
On 16/06/2026 2:23 AM, Denis Feklushkin wrote:On Monday, 15 June 2026 at 10:35:39 UTC, Denis Feklushkin wrote:The implementation can be extracted into a package struct. Nothing needs to break to fix this.On Monday, 15 June 2026 at 09:41:00 UTC, Denis Feklushkin wrote:The attempt to use standard Semaphore and Mutex in ondition implementation failed because the current Condition semantics requires nogc, but Mutex and Semaphore are classes and std.typecons.scoped isn't available in druntime.Most likely, these primitives do not exist in any OS - they are too high-level and can be implemented on the basis of "more primitive" primitives. (Posix implementation just provides convient wrapper, I think)It is possible make PR on this base which will satisfy everyone. However, I'll wait for information about Windows (see previous message).This is another argument for moving this code to PhobosThere is no valid argument here. To move it requires breaking user code, and that is not an option.
Jun 15
On Monday, 15 June 2026 at 23:50:01 UTC, Richard (Rikki) Andrew Cattermole wrote:This leads to duplication of code what already available in `std.typecons.scoped`The attempt to use standard Semaphore and Mutex in ondition implementation failed because the current Condition semantics requires nogc, but Mutex and Semaphore are classes and std.typecons.scoped isn't available in druntime.The implementation can be extracted into a package struct.Nothing needs to break to fix this.Why you use "break" to describe this? I do not propose break anything: I propose to add `public import` from `std.concurrency.rwmutex` (etc) into `core.sync.rwmutex` module with appropriate deprecation messages.Related - "Very telling quote": https://forum.dlang.org/post/lkfdcbhqjdphvoaekpxq forum.dlang.org (Very telling quote)This is another argument for moving this code to PhobosThere is no valid argument here. To move it requires breaking user code, and that is not an option.
Jun 16
On 16/06/2026 8:15 PM, Denis Feklushkin wrote:On Monday, 15 June 2026 at 23:50:01 UTC, Richard (Rikki) Andrew Cattermole wrote:No. I did not suggest anything to do with scoped. All of the state and function calls to make it platform independent does not need to live in a class. It can live in a struct instead and then be called into. ```d class Thing { private Thing2 thing2; void call() => thing2.call(); } package: struct Thing2 { void* state; void call() { } } ```This leads to duplication of code what already available in `std.typecons.scoped`The attempt to use standard Semaphore and Mutex in ondition implementation failed because the current Condition semantics requires nogc, but Mutex and Semaphore are classes and std.typecons.scoped isn't available in druntime.The implementation can be extracted into a package struct.Druntime cannot import phobos. Phobos depends upon druntime. Binary loading is acyclic, not cyclic. No PR that tries to do this will be merged.Nothing needs to break to fix this.Why you use "break" to describe this? I do not propose break anything: I propose to add `public import` from `std.concurrency.rwmutex` (etc) into `core.sync.rwmutex` module with appropriate deprecation messages.
Jun 16
On Tuesday, 16 June 2026 at 08:23:11 UTC, Richard (Rikki) Andrew Cattermole wrote:Druntime cannot import phobos. Phobos depends upon druntime. Binary loading is acyclic, not cyclic.By the way, this is off-topic, I have one more suggestion on this matter sounding like: "druntime cannot import core.stdc" I.e., core.stdc shouldn't be necessary. Let the druntime use these functions through wrapper functions. There will be only about 10 of them in total, I think: malloc/free, some sync methods... This will solve 95% of porting issues to any system
Jun 16
On 16/06/2026 10:32 PM, Denis Feklushkin wrote:On Tuesday, 16 June 2026 at 08:23:11 UTC, Richard (Rikki) Andrew Cattermole wrote:Chuck it into a module called core.internal.platform and sure. You shouldn't need wrapper functions for the most part. Aliases will suffice. I.e. malloc is perfectly fine as an API, just needs a different name so it can be swapped out easily.Druntime cannot import phobos. Phobos depends upon druntime. Binary loading is acyclic, not cyclic.By the way, this is off-topic, I have one more suggestion on this matter sounding like: "druntime cannot import core.stdc" I.e., core.stdc shouldn't be necessary. Let the druntime use these functions through wrapper functions. There will be only about 10 of them in total, I think: malloc/free, some sync methods... This will solve 95% of porting issues to any system
Jun 16
On Tuesday, 16 June 2026 at 10:38:27 UTC, Richard (Rikki) Andrew Cattermole wrote:Yes, maybe aliases. Point is in restrictions for druntime developers to avoid them to use core.stdc functions directly exept available ~10 aliases, same on all platforms, same for Posix, non-Posix, with libc or without - this doesn't matterI.e., core.stdc shouldn't be necessary. Let the druntime use these functions through wrapper functions. There will be only about 10 of them in total, I think: malloc/free, some sync methods... This will solve 95% of porting issues to any systemChuck it into a module called core.internal.platform and sure. You shouldn't need wrapper functions for the most part. Aliases will suffice. I.e. malloc is perfectly fine as an API, just needs a different name so it can be swapped out easily.
Jun 16
On 16/06/2026 10:48 PM, Denis Feklushkin wrote:On Tuesday, 16 June 2026 at 10:38:27 UTC, Richard (Rikki) Andrew Cattermole wrote:Yeah its a known issue with druntime when it comes to porting it. Its very all or nothing. So it was an easy yes, and I doubt anyone will have an opinion against it.Yes, maybe aliases. Point is in restrictions for druntime developers to avoid them to use core.stdc functions directly exept available ~10 aliases, same on all platforms, same for Posix, non-Posix, with libc or without - this doesn't matterI.e., core.stdc shouldn't be necessary. Let the druntime use these functions through wrapper functions. There will be only about 10 of them in total, I think: malloc/free, some sync methods... This will solve 95% of porting issues to any systemChuck it into a module called core.internal.platform and sure. You shouldn't need wrapper functions for the most part. Aliases will suffice. I.e. malloc is perfectly fine as an API, just needs a different name so it can be swapped out easily.
Jun 16
On Tuesday, 16 June 2026 at 08:23:11 UTC, Richard (Rikki) Andrew Cattermole wrote:Condition class currently isn't cross-platform. Making it so is a another separate task. Moving it into Phobos for future generations to improvement would be the best solution, in my opinion. (Just at the moment when the rest druntime functionality for baremetal/multiplatform support is ready, Phobos 3 will appear, in which this can be taken into account.)This leads to duplication of code what already available in `std.typecons.scoped`No. I did not suggest anything to do with scoped. All of the state and function calls to make it platform independent does not need to live in a class.Oh, yes, you are right here. But we can copy and paste code to Phobos and deprecate same code in the drumtime for ~year. Obvious, anyone using Barrier class will be able to change the import line from core.sync.barrier to std.concurrency.barrierDruntime cannot import phobos.Nothing needs to break to fix this.Why you use "break" to describe this? I do not propose break anything: I propose to add `public import` from `std.concurrency.rwmutex` (etc) into `core.sync.rwmutex` module with appropriate deprecation messages.
Jun 16
On Monday, 15 June 2026 at 23:50:01 UTC, Richard (Rikki) Andrew Cattermole wrote:To move it requires breaking user code, and that is not an option.Why not do what we typically did in the past - mark it deprecated with message that we are not deprecating it but actually moving somewhere else, and then after few months actually do it? Instead of repeating C++ mistakes, let's not fear breaking changes, and learn how to do them the right way... - If something is marked as deprecated with appropriate message for 6 months those who complain about broken code after that period, when the move actually happened should just, put it bluntly, shut the heck up.
Jun 16
On 16/06/2026 9:54 PM, Dejan Lekic wrote:On Monday, 15 June 2026 at 23:50:01 UTC, Richard (Rikki) Andrew Cattermole wrote:1. It would need to be more like 6 years, not 6 months with such long release cycles. 2. There is nothing actually wrong with the code, it is working correctly. 3. All multi-threaded OS's should support these primitives. 4. There are alternatives to breaking code that are a better choice. There is a time and a place to break code, this isn't it.To move it requires breaking user code, and that is not an option.Why not do what we typically did in the past - mark it deprecated with message that we are not deprecating it but actually moving somewhere else, and then after few months actually do it? Instead of repeating C++ mistakes, let's not fear breaking changes, and learn how to do them the right way... - If something is marked as deprecated with appropriate message for 6 months those who complain about broken code after that period, when the move actually happened should just, put it bluntly, shut the heck up.
Jun 16
On Tuesday, 16 June 2026 at 10:21:43 UTC, Richard (Rikki) Andrew Cattermole wrote:There is a time and a place to break code, this isn't it.This is all good, but could you clearly specify the path for FreeRTOS support? How and when this could happen?
Jun 16
On 16/06/2026 10:27 PM, Serg Gini wrote:On Tuesday, 16 June 2026 at 10:21:43 UTC, Richard (Rikki) Andrew Cattermole wrote:I have given two good options to handle these two classes. Version them off like we do for bindings, or implement them on other primitives (which is common practice for that OS). Versioning is the quickest solution, and allows someone to come back later to implement the standard way. I have no preference of these two.There is a time and a place to break code, this isn't it.This is all good, but could you clearly specify the path for FreeRTOS support? How and when this could happen?
Jun 16
On Tuesday, 16 June 2026 at 10:21:43 UTC, Richard (Rikki) Andrew Cattermole wrote:3. All multi-threaded OS's should support these primitives.Why? Because someone 20 years ago, apparently by accident, implemented this code in the druntime? This code isn't necessary for the druntime, that's the point. And the operating system doesn't necessarily need to support it either. It's (I repeat myself, excuse me) too high-level sync primitive, and not all OSes can provide it.
Jun 16
On 16/06/2026 10:37 PM, Denis Feklushkin wrote:On Tuesday, 16 June 2026 at 10:21:43 UTC, Richard (Rikki) Andrew Cattermole wrote:So version it off like we do with bindings. There is no reason to break existing code when we can do that. ```d version(FreeRTOS) version = NoBarrier; version(NoBarrier) { disable class Barrier {} } else { class Barrier { ... } } ```3. All multi-threaded OS's should support these primitives.Why? Because someone 20 years ago, apparently by accident, implemented this code in the druntime? This code isn't necessary for the druntime, that's the point. And the operating system doesn't necessarily need to support it either. It's (I repeat myself, excuse me) too high-level sync primitive, and not all OSes can provide it.
Jun 16
On Tuesday, 16 June 2026 at 10:41:00 UTC, Richard (Rikki) Andrew Cattermole wrote:So version it off like we do with bindings. There is no reason to break existing code when we can do that. ```d version(FreeRTOS) version = NoBarrier; ```But this will break existing code which using Barrier when cross-compiling for FreeRTOS :-)
Jun 16
On 16/06/2026 11:12 PM, Denis Feklushkin wrote:On Tuesday, 16 June 2026 at 10:41:00 UTC, Richard (Rikki) Andrew Cattermole wrote:Nobody is compiling for FreeRTOS using upstream druntime if it hasn't been ported. So there is nothing to break.So version it off like we do with bindings. There is no reason to break existing code when we can do that. ```d version(FreeRTOS) version = NoBarrier; ```But this will break existing code which using Barrier when cross- compiling for FreeRTOS :-)
Jun 16
On Tuesday, 16 June 2026 at 11:14:25 UTC, Richard (Rikki) Andrew Cattermole wrote:Nobody is compiling for FreeRTOS using upstream druntime if it hasn't been ported. So there is nothing to break.I claim that this is accidentally added code that has been used in open source projects ~3 times or so (throughout the history of GitHub), and PRs what using of this code was rejected twice. Once code was sucessfully used 8 years ago in some 3rd party open project. Your opinion: we don't change our API because it will break user code. :-/ At the same time, there is no reason at the present time to make a cross-platform implementation of this algorithm - writing a such code "for the future" means planting a bomb under someone else's code because it will not be properly tested and used now. (Yes, my personal opinion is that it is not needed at all in std libraries) FreeRTOS: I'm only interested in it because it's unlike anything else we use in D. That is, if we implement support for it, we'll get a highly abstract druntime, which will make it much easier to add more traditional OSes/platforms. Ok, next: Windows will die in ~10 years (or maybe 15, yeah right! Many of us already using D more than 15 years, just to orient on the timeline. Who among us at that time would have believed that Linux would be built into Windows?) Posix is a dead end, even for Linux (we could at least allocate memory not by maloc/free wrappers?) Obviously, new OSes will emerge on such timeline, at the very least because new types of hardware (persistent RAM?) will emerge. These OSes will use different APIs. How long has the battle for Wasm been going on? (Yes, I know there's a different problem there.) There's still no bare metal support, after ~15 years. Some kind of stagnation? On GitHub I found only one use of classes mentioned in this tpic, in code that's 8 years old. Let's break this classes, especially since it won't disappear, but will remain in Phobos!
Jun 16
On Tuesday, 16 June 2026 at 12:19:27 UTC, Denis Feklushkin wrote:On Tuesday, 16 June 2026 at 11:14:25 UTC, Richard (Rikki)Let's break this classes, especially since it won't disappear, but will remain in Phobos!(The train of thought suddenly stopped) Otherwise, without such decisions all ecosystem will remain to rot without any forward movement
Jun 16
On Tuesday, 16 June 2026 at 10:41:00 UTC, Richard (Rikki) Andrew Cattermole wrote:So version it off like we do with bindings. There is no reason to break existing code when we can do that. ```d version(FreeRTOS) version = NoBarrier; ```But this will break existing code which using Barrier when cross-compiling for FreeRTOS :-)
Jun 16
On Tuesday, 16 June 2026 at 10:41:00 UTC, Richard (Rikki) Andrew Cattermole wrote:```d version(NoBarrier) { disable class Barrier {} } else { ```` disable` doesn't work with types. You can do ` disable new();` though. The spec should be clearer:A reference to a declaration marked with the disable attribute causes a compile time error.https://dlang.org/spec/attribute.html#disable
Jun 17
On 18/06/2026 7:19 AM, Nick Treleaven wrote:On Tuesday, 16 June 2026 at 10:41:00 UTC, Richard (Rikki) Andrew Cattermole wrote:That should really be fixed to make disable work on types.```d version(NoBarrier) { disable class Barrier {} } else { ```` disable` doesn't work with types. You can do ` disable new();` though. The spec should be clearer:A reference to a declaration marked with the disable attribute causes a compile time error.https://dlang.org/spec/attribute.html#disable
Jun 17
On Wednesday, 17 June 2026 at 19:19:41 UTC, Nick Treleaven wrote:On Tuesday, 16 June 2026 at 10:41:00 UTC, Richard (Rikki) Andrew Cattermole wrote:Filed issue & PR: https://github.com/dlang/dmd/issues/23289```d version(NoBarrier) { disable class Barrier {} } else { ```` disable` doesn't work with types. You can do ` disable new();` though. The spec should be clearer:
Jun 20
Thank you for your work supporting FreeRTOS! I recommend checking github on the history of those functions. The PR's for them may give a rationale for their existence.
Jun 15
On Monday, 15 June 2026 at 21:06:16 UTC, Walter Bright wrote:Thank you for your work supporting FreeRTOS! I recommend checking github on the history of those functions. The PR's for them may give a rationale for their existence.In dmd repository first commit containing mentioned above classes is literally the first commit that makes any sense: ``` commit 6837c0cd426f7e828aec1a2bdc941ac9b722dd14 (HEAD) Author: Sean Kelly <sean invisibleduck.org> Date: Fri Sep 19 02:35:12 2008 +0000 First commit of the D Runtime Project. This includes a fully functional runtime for DMD/D1. Support for DMD/D2 is next on the agenda. ``` And I see that this classes simply exist and are not used anywhere. I used commands like: ``` git log -G " Barrier" ``` to find anything. I also searched in Phobos repository and didn't find anything. Github reports one unsuccessful attempt to make PR with ReadWriteMutex, but it was declined. Maybe I'm looking in the wrong place, I'm not a big expert on git kung fu.
Jun 15









Denis Feklushkin <feklushkin.denis gmail.com> 