Re: While loop on global variable optimised away?
On Wednesday, 11 May 2022 at 10:01:18 UTC, Johan wrote: Any function call (inside the loop) for which it cannot be proven that it never modifies your memory variable will work. That's why I'm pretty sure that mutex lock/unlock will work. Thank you, in C I would not have been surprised. It was the default thread local storage that made me question it. Your remark about the mutex lock/unlock is very helpful, I was starting to get worried I would need to keep a very careful watch on those __gshareds [well, more than usual :) ]
While loop on global variable optimised away?
Hi Forum, I have a snippet of code as follows: ``` extern(C) extern __gshared uint g_count; // inside a class member function: while(g_count) <= count) {} ``` This is from a first draft of the code without proper thread synchronisation. The global variable g_count is updated from a bit of C++ code. As soon as I turn the optimiser on, the code never gets passed this point, leading me to suspect it gets turned into ``` while(true) {} ``` If modify the code in the following way: ``` import core.volatile : volatileLoad; while(volatileLoad(_count) <= count) {} ``` it works again. My question is, have I hit a compiler bug (ldc 1.28.1, aarch64 [Raspberry Pi]) or is this part of the language design. I would have thought since D use thread-local storage by default, that for a __gshared variable it would be understood that it can get modified by another thread. Access through atomic function would prevent the compiler from optimising this away as well, but if I were to use a Mutex inside the loop, there is no way for the compiler to tell *what* that Mutex is protecting and it might still decide to optimise the test away (assuming that is what is happening, did not attempt to look at the assembler code). Cheers
Re: Use bindbc-sdl statically
On Saturday, 24 April 2021 at 16:44:09 UTC, Ishax wrote: So I have the lib files. It's failing with only an exit code. No window is appearing. It's using the same D code as with the dynamic setup which I was able to produce a window with. ```sdl dependency "bindbc-sdl" version="~>0.1.0" versions "BindSDL_Static" subConfigurations "bindbc-sdl" "staticBC" libs "SDL2" "SDL2_image" ``` Hi, Linux programmer here who just went through the process of working with dll's and lib's on windows. In my current understanding, there are three ways of working with libraries: 1. Load DLL's at runtime (LoadLibrary and such) 2. Linking with DLL's at compile time. The compiler adds code to automatically load the DLL's when your program starts. You do this by linking against an *import library*. These have a *.lib* extension 3. Linking against *static libraries*. These have a *.lib* extension Note that 2. & 3. are different things, but the files you need end in .lib in both cases. You'll have to check that your .lib files are actually static libraries, not import libraries. I am not sure if linking to outside sources is appropriate, so I will just copy-paste from stackoverflow: "Use the lib command. If it's static, lib will show you a pile of .obj files inside. Not so if it's am implib." lib /list foo.lib
Re: Dlang equivalent of #define/#ifdef : not... version
On Tuesday, 20 April 2021 at 18:57:46 UTC, ichneumwn wrote: Hi, Trying to convert a C header to D. The underlying package exists in different versions and may or may not expose certain functionality (modules/extensions). One should check at compile time that the header provides the relevant definitions, through #ifdef, and do a further run-time check to confirm the functionality is really present. It is the compile time check that I am finding tricky to do/emulate. .h : #define i_am_a_feature 1 The C-code uses this define as a guard: .c : #ifdef i_am_a_feature What would the the D equivalent? This is my attempt so far: features.d: import std.traits; private enum capabilities { i_am_a_feature } template supported(string member) { enum bool supported = hasMember!(capabilities, member); } version = vs_i_am_a_feature; enum can_i_test_for_this; and use.d: import features; import std.stdio; void main() { static if (supported!("i_am_a_feature")) { writeln("Feature 1!"); } static if (supported!("i_am_not_a_feature")) { writeln("Feature 2!"); } version(vs_i_am_a_feature) { writeln("If only I worked"); } } This produces "Feature 1!", so the supported() path works, but is a bit of a round-about way and all "capability flags" need to put in that single enum capabilities instead of being allowed to be scattered across the features.d module. As is documented, "version" does not cross the module boundary. So my questions: - is there a module-crossing equivalent of "version"? - if not, is there some way I could test for the existence of the enum can_i_test_for_this? A SymbolExists!() or ModuleHasSymbol!() or ModuleHasMember!() ? Cheers Between them, Simen and Ali have cracked the case. Ali's demonstration that "true" was returned made me look at it further and tried the module's name directly and that worked too. It seems that Simen's expansion of hasMember() into the __traits version does the trick -- the __traits version *does* accept the module as a parameter. It seems the template expansion does not like module arguments, not __traits itself. Here is the demo: features.d: import std.traits; enum can_sing = 1; enum can_dance = 1; template supported(string member) { enum bool supported = __traits(hasMember, features, member); // features can be replaced by: mixin(__MODULE__) // to make this module robust against renaming } /* * Note that using std.traits.hasMember *does not* work. Yields error: * template instance hasMember!(features, "can_sing") does not match template * declaration hasMember(T, string name) */ use.d: import features; import std.stdio; import std.traits; void main() { static if (supported!"can_sing") { writeln("can_sing"); } static if (supported!("can_dance")) { writeln("can_dance"); } static if (supported!("can_jump")) { writeln("can_jump"); } } Result: can_sing can_dance I think the version with the mixin is neater, but I have put it in the direct "features" in the example to show it is not actually necessary. Oh, I found a bonus option: passing the module as an argument. I do not really get templates beyond the very basic ones, but I remember seeing "alias" somewhere and that gets the module through my own template: // accept module as argument template supported(alias modname, string member) { enum bool supported = __traits(hasMember, modname, member); } // accept module name (string) as argument: template supported(string modname, string member) { enum bool supported = __traits(hasMember, mixin(modname), member); } As I write this, I realise that the alias can also be used to get a version of hasMember that accepts modules: enum hasMember(alias T, string name) = __traits(hasMember, T, name); Although that might have unintended side effects? And, indeed, shorten my own use case to: enum supported(string member) = __traits(hasMember, mixin(__MODULE__), member); Many thanks to everyone with suggestions!
Re: write once type?
On Tuesday, 20 April 2021 at 20:04:17 UTC, Steven Schveighoffer wrote: I just realized, this is Rebindable, or tail-const. (I don't need the head to be truly const, I just need to be able to copy into a const-referring thing). I currently am using a pointer, which is working, but I prefer not to use it, and it is not general enough. -Steve Ah, you found it - I was looking up the reference for it and you replied in the mean-time. Ignore my answer :)
Re: write once type?
On Tuesday, 20 April 2021 at 19:56:33 UTC, Steven Schveighoffer wrote: I have had the need in some cases to *maybe* set a const value inside a loop. One can sometimes abstract this into a lambda function, but sometimes this is not possible (e.g. if the loop is static). Not only that, but I may also want to keep processing the loop and do something different if the value has already been set instead of returning immediately, which necessitates a second loop. My use case is I have a property that is const inside a set of types, and I want to verify that they all have the same value, and extract what that value is. I'm wondering if anyone has a "Write once" type, that is, a type that allows you to write it exactly once, and is treated like initialization on first setting (i.e. allows writing to previously unused const data). This type has to decide at runtime whether it has been set. So it would kind of be like Nullable!T, but Nullable doesn't allow setting when the T is const. Optional!T doesn't work either. -Steve Not quite your use case, I think, but std.typecons.Rebindable at least allows you to bind a new const(object). Not write once though. I think I found that after a hint of its existence in https://forum.dlang.org/thread/orpbvvjspibfpitnn...@forum.dlang.org
Dlang equivalent of #define/#ifdef : not... version
Hi, Trying to convert a C header to D. The underlying package exists in different versions and may or may not expose certain functionality (modules/extensions). One should check at compile time that the header provides the relevant definitions, through #ifdef, and do a further run-time check to confirm the functionality is really present. It is the compile time check that I am finding tricky to do/emulate. .h : #define i_am_a_feature 1 The C-code uses this define as a guard: .c : #ifdef i_am_a_feature What would the the D equivalent? This is my attempt so far: features.d: import std.traits; private enum capabilities { i_am_a_feature } template supported(string member) { enum bool supported = hasMember!(capabilities, member); } version = vs_i_am_a_feature; enum can_i_test_for_this; and use.d: import features; import std.stdio; void main() { static if (supported!("i_am_a_feature")) { writeln("Feature 1!"); } static if (supported!("i_am_not_a_feature")) { writeln("Feature 2!"); } version(vs_i_am_a_feature) { writeln("If only I worked"); } } This produces "Feature 1!", so the supported() path works, but is a bit of a round-about way and all "capability flags" need to put in that single enum capabilities instead of being allowed to be scattered across the features.d module. As is documented, "version" does not cross the module boundary. So my questions: - is there a module-crossing equivalent of "version"? - if not, is there some way I could test for the existence of the enum can_i_test_for_this? A SymbolExists!() or ModuleHasSymbol!() or ModuleHasMember!() ? Cheers
Re: Linux shared library loading/linking from C does not invoke (shared) static this
On Tuesday, 12 January 2021 at 09:49:46 UTC, Mike Parker wrote: On Tuesday, 12 January 2021 at 09:31:08 UTC, ichneumwn wrote: Follow on to my own question: on Linux, with gcc, I have created the following file "starter.c" that I inject into my D shared library: int rt_init(void); int rt_term(void); // should really check for errors! static void __attribute__((constructor)) Dstarter(void) { rt_init(); } static void __attribute__((destructor)) Dterminator(void) { rt_term(); } That seems to do the trick. Not sure how clean this is? You should be able to do the same in D with `pragma(crt_constructor)` and `pragma(crt_destructor)`: https://dlang.org/spec/pragma.html#crtctor https://dlang.org/spec/pragma.html#crtdtor https://dlang.org/changelog/2.078.0.html#crt-constructor Perfect, thanks! Interestingly, as I removed the C stub and tried the D route, I noticed that just calling rt_init() is enough to also get static ~this() to run on exit. In fact then adding writeln in a pragma(crt_destructor) function shows that it gets called after static ~this(). For anyone stumbling across this thread and looking for the import for rt_init/term: import core.runtime : rt_init, rt_term;
Re: Linux shared library loading/linking from C does not invoke (shared) static this
On Tuesday, 12 January 2021 at 09:02:38 UTC, Imperatorn wrote: On Tuesday, 12 January 2021 at 08:19:45 UTC, ichneumwn wrote: Where could one file a suggestion for an update to the documentation? In the top right section of the page you can click the "Improve this page"-link. Thanks, I will leave it though. I do not want to mess about and write about something I have just learnt in the last hour. That could do more damage than good.
Re: Linux shared library loading/linking from C does not invoke (shared) static this
On Tuesday, 12 January 2021 at 08:19:45 UTC, ichneumwn wrote: Dear all, I was trying to invoke some D code from Python and ran into issues which I eventually traced back to a simple example on the D website itself : https://dlang.org/articles/dll-linux.html Particularly the section "Dynamically Loading a D DLL From a C Program" In my case, and indeed already in 2013 (https://forum.dlang.org/post/yeqyqaaguhngczlnv...@forum.dlang.org), shared static this does not get invoked I normally use: LDC - the LLVM D compiler (1.21.0): based on DMD v2.091.1 and LLVM 10.0.0 (under Linux) but I also tried DMD64 D Compiler v2.095.0 Is the solution suggested in the linked post the "canonical way"? Where could one file a suggestion for an update to the documentation? Cheers! PS Enjoying my project in D especially how easy it is to get the same code to run under windows too Follow on to my own question: on Linux, with gcc, I have created the following file "starter.c" that I inject into my D shared library: int rt_init(void); int rt_term(void); // should really check for errors! static void __attribute__((constructor)) Dstarter(void) { rt_init(); } static void __attribute__((destructor)) Dterminator(void) { rt_term(); } That seems to do the trick. Not sure how clean this is?
Linux shared library loading/linking from C does not invoke (shared) static this
Dear all, I was trying to invoke some D code from Python and ran into issues which I eventually traced back to a simple example on the D website itself : https://dlang.org/articles/dll-linux.html Particularly the section "Dynamically Loading a D DLL From a C Program" In my case, and indeed already in 2013 (https://forum.dlang.org/post/yeqyqaaguhngczlnv...@forum.dlang.org), shared static this does not get invoked I normally use: LDC - the LLVM D compiler (1.21.0): based on DMD v2.091.1 and LLVM 10.0.0 (under Linux) but I also tried DMD64 D Compiler v2.095.0 Is the solution suggested in the linked post the "canonical way"? Where could one file a suggestion for an update to the documentation? Cheers! PS Enjoying my project in D especially how easy it is to get the same code to run under windows too
Re: Waiting on file descriptor/socket *AND* thread messages
On Monday, 29 June 2020 at 12:25:16 UTC, Steven Schveighoffer wrote: On 6/29/20 5:14 AM, ichneumwn wrote: [...] Not in the standard library. Such things require an event framework, because there is no OS-agnostic provided mechanism to sleep on all these things at once. I recommend looking through code.dlang.org. I found these: https://code.dlang.org/packages/libasync https://code.dlang.org/packages/eventcore https://code.dlang.org/packages/mecca (this seems very underdocumented, but I know it provides such a system) [...] I don't know the correct way to solve this, I've done it in the past by creating a file descriptor that can be waited on to wake up the target along with any other file descriptors being waited on. -Steve Thanks for the pointers Steve!
Waiting on file descriptor/socket *AND* thread messages
Dear all, Is there some facility in D for a single statement/function call that will wait on both file descriptors, like Socket.select(), and will also wake up when there is something to be receive()'d? One solution would be to have my main thread use receive() and a helper thread that does the select() call and sends a message to the main thread. That seems a bit of overkill however. Apologies if this has been asked before, but my google search and search in this thread were fruitless (could be my searching skills) Cheers