Re: Program exited with code -11 when calling
bson_t* bson_new_from_json(in char* data, long len, bson_error_t* error); string str_utf8 = "{\"a\":1}"; bson_error_t error; auto bson = bson_new_from_json(str_utf8.ptr, str_utf8.length, ); You have a wrong declaration for bson_error_t too.
Re: Program exited with code -11 when calling
On Wednesday, 1 July 2020 at 05:33:48 UTC, H. S. Teoh wrote: On Wed, Jul 01, 2020 at 05:04:28AM +, Anthony via Digitalmars-d-learn wrote: [...] auto str_utf8 = str.toUTF8(); bson_error_t error auto bson = bson_new_from_json(cast(const uint8_t*)str_utf8.ptr, -1, ); I get a "Program exited with code -11" message. Does anyone know what I'm doing wrong? D strings are generally not null-terminated (except for literals). Before passing them to a C function you need to add a trailing null. Try using std.conv.toStringz instead of casting the pointer yourself. T Thanks H. S. Teoh. Hmm, still same result though. import std.string; auto str = toStringz("{\"a\":1}"); bson_error_t error; bson_new_from_json(str, -1, ); extern(C) { ... bson_t* bson_new_from_json(const char* data, long len, bson_error_t* error); }
Re: Linking D with C structs
On Monday, 29 June 2020 at 10:44:16 UTC, kinke wrote: On Monday, 29 June 2020 at 06:29:38 UTC, Anthony wrote: What does "__initZ" refer to? Does this refer to automatic initialization like "this()"? Almost, it's the static initializer for that struct, which is omitted because you apparently don't compile/link the module containing the struct declaration. Initialize the char array with zeros (= 0) to make the struct fully zero-initialized, preventing the need for that symbol. chars in D are initialized with 0xFF, unlike byte and ubyte. Thanks for this! What do you mean by "which is omitted because you apparently don't compile/link the module containing the struct declaration"? Is there a link step that I'm missing that will make things easier for me? Is there a way to have D automatically get the struct from the c files directly?
Re: Program exited with code -11 when calling
On Wednesday, 1 July 2020 at 05:09:47 UTC, Cym13 wrote: On Wednesday, 1 July 2020 at 05:04:28 UTC, Anthony wrote: I'm trying to convert this c function: bson_t *bson_new_from_json (const uint8_t *data, ssize_t len, bson_error_t *error); Into a D function. This is my attempt: extern(C) { struct bson_t; struct bson_error_t; bson_t* bson_new_from_json(const uint8_t* data, long len, bson_error_t* error); } However when I try it, for example: auto str_utf8 = str.toUTF8(); bson_error_t error auto bson = bson_new_from_json(cast(const uint8_t*)str_utf8.ptr, -1, ); I get a "Program exited with code -11" message. Does anyone know what I'm doing wrong? Thanks I don't know the exact function you are trying to use, but -11 means "segmentation fault" on linux. This means that your program is trying to read or write a memory location that it is not supposed to. This typically happens during buffer overflows and similar memory corruption bugs. One thing that jumps to me is the -1 in your call instead of the length. Without knowing the C function's implementation I would expect it to mean either "read before the array" which would be a buffer overflow or to have the special meaning of "deduce the string size yourself". In that last case I would expect bson_new_from_json to expect a NUL-terminated array, but I don't know if your UTF8 array is NUL-terminated. Thanks for getting back to me. Yeah I figured it was a segmentation fault, however, I don't know exactly how to pinpoint where this is happening. I'm wondering if there's anything wrong with how I'm casting the data since everything is self contained (assuming bson_new_from_json is correct since it works using c directly). void foo() { import std.utf; import core.stdc.stdint; auto str_utf8 = "{\"a\":1}"; bson_error_t error; bson_new_from_json(cast(uint8_t*)str_utf8, (cast(uint8_t[])str_utf8).length, ); } Re -1 in the call: Apparently it uses strlen() to deduce the size. However, I tried explicitly state the array length but had no luck.
Re: Program exited with code -11 when calling
On Wed, Jul 01, 2020 at 05:04:28AM +, Anthony via Digitalmars-d-learn wrote: [...] > auto str_utf8 = str.toUTF8(); > bson_error_t error > > auto bson = bson_new_from_json(cast(const uint8_t*)str_utf8.ptr, -1, > ); > > > I get a "Program exited with code -11" message. > Does anyone know what I'm doing wrong? D strings are generally not null-terminated (except for literals). Before passing them to a C function you need to add a trailing null. Try using std.conv.toStringz instead of casting the pointer yourself. T -- A programming language should be a toolbox for the programmer to draw upon, not a minefield of dangerous explosives that you have to very carefully avoid touching in the wrong way.
Re: Program exited with code -11 when calling
On Wednesday, 1 July 2020 at 05:04:28 UTC, Anthony wrote: I'm trying to convert this c function: bson_t *bson_new_from_json (const uint8_t *data, ssize_t len, bson_error_t *error); Into a D function. This is my attempt: extern(C) { struct bson_t; struct bson_error_t; bson_t* bson_new_from_json(const uint8_t* data, long len, bson_error_t* error); } However when I try it, for example: auto str_utf8 = str.toUTF8(); bson_error_t error auto bson = bson_new_from_json(cast(const uint8_t*)str_utf8.ptr, -1, ); I get a "Program exited with code -11" message. Does anyone know what I'm doing wrong? Thanks I don't know the exact function you are trying to use, but -11 means "segmentation fault" on linux. This means that your program is trying to read or write a memory location that it is not supposed to. This typically happens during buffer overflows and similar memory corruption bugs. One thing that jumps to me is the -1 in your call instead of the length. Without knowing the C function's implementation I would expect it to mean either "read before the array" which would be a buffer overflow or to have the special meaning of "deduce the string size yourself". In that last case I would expect bson_new_from_json to expect a NUL-terminated array, but I don't know if your UTF8 array is NUL-terminated.
Program exited with code -11 when calling
I'm trying to convert this c function: bson_t *bson_new_from_json (const uint8_t *data, ssize_t len, bson_error_t *error); Into a D function. This is my attempt: extern(C) { struct bson_t; struct bson_error_t; bson_t* bson_new_from_json(const uint8_t* data, long len, bson_error_t* error); } However when I try it, for example: auto str_utf8 = str.toUTF8(); bson_error_t error auto bson = bson_new_from_json(cast(const uint8_t*)str_utf8.ptr, -1, ); I get a "Program exited with code -11" message. Does anyone know what I'm doing wrong? Thanks
Re: Why is this allowed
On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote: Spent some time debugging because I didn't notice it at first, essentially something like this: int[3] foo = [1, 2, 3]; foo = 5; writeln(foo); // 5, 5, 5 Why does such code compile? I don't think this should be permitted, because it's easy to make a mistake (when you wanted foo[index] but forgot the []). If someone wants to assign a value to every element they could do foo[] = 5; instead which is explicit. auch, that is very nasty. Thanks for posting. This is a good example for D gotchas.
Re: idiomatic output given -preview=nosharedaccess ,
On Tuesday, 30 June 2020 at 20:12:59 UTC, Stanislav Blinov wrote: On Tuesday, 30 June 2020 at 20:04:33 UTC, Steven Schveighoffer wrote: The answer is -- update Phobos so it works with -nosharedaccess :) Yeah... and dip1000. And dip1008. And dip... :) Didn't want to be snippity but, yeah, with "hello world" breaking I thought it was time to fix the standard library. Thanks for the polite confirmation(s).
Re: Privatize a few members to allow messing with them #11353
On Tuesday, 30 June 2020 at 20:01:43 UTC, Stanislav Blinov wrote: On Tuesday, 30 June 2020 at 19:58:05 UTC, matheus wrote: +loc.linnum = loc.linnum + incrementLoc; This works because it was declared: void linnum(uint rhs) { _linnum = rhs; } Right? Almost. Given these definitions: @safe @nogc pure @property { const uint linnum() { return _linnum; } void linnum(uint rhs) { _linnum = rhs; } } This: loc.linnum = loc.linnum + incrementLoc; is rewritten as: loc.linnum(loc.linnum() + incrementLoc); Alright and thanks again. Matheus.
Re: idiomatic output given -preview=nosharedaccess ,
On Tuesday, 30 June 2020 at 20:04:33 UTC, Steven Schveighoffer wrote: The answer is -- update Phobos so it works with -nosharedaccess :) Yeah... and dip1000. And dip1008. And dip... :)
Re: idiomatic output given -preview=nosharedaccess ,
On 6/30/20 3:56 PM, Bruce Carneal wrote: Given -preview=nosharedaccess on the command line, "hello world" fails to compile (you are referred to core.atomic ...). What is the idiomatic way to get writeln style output from a nosharedaccess program? Is separate compilation the way to go? writeln uses the shared stdout. The answer is -- update Phobos so it works with -nosharedaccess :) -Steve
Re: Privatize a few members to allow messing with them #11353
On Tuesday, 30 June 2020 at 19:58:05 UTC, matheus wrote: +loc.linnum = loc.linnum + incrementLoc; This works because it was declared: void linnum(uint rhs) { _linnum = rhs; } Right? Almost. Given these definitions: @safe @nogc pure @property { const uint linnum() { return _linnum; } void linnum(uint rhs) { _linnum = rhs; } } This: loc.linnum = loc.linnum + incrementLoc; is rewritten as: loc.linnum(loc.linnum() + incrementLoc);
Re: Privatize a few members to allow messing with them #11353
On Tuesday, 30 June 2020 at 19:55:56 UTC, matheus wrote: On Tuesday, 30 June 2020 at 19:46:35 UTC, Stanislav Blinov ... @safe @nogc pure @property { const uint linnum() { return _linnum; } const uint charnum() { return _charnum; } void linnum(uint rhs) { _linnum = rhs; } void charnum(uint rhs) { _charnum = rhs; } } ...with which the += won't work (at least this variant, as the getter isn't returning ref). Oh I see now and thanks for the information. By the way: +loc.linnum = loc.linnum + incrementLoc; This works because it was declared: void linnum(uint rhs) { _linnum = rhs; } Right? Matheus.
Re: Privatize a few members to allow messing with them #11353
On Tuesday, 30 June 2020 at 19:46:35 UTC, Stanislav Blinov wrote: On Tuesday, 30 June 2020 at 19:42:57 UTC, matheus wrote: in this case this was more a style thing than anything else right? Or is there something I'm not able to see? Before the change, linnum and charnum are public variables, one can do a += on them. After the change, they become properties accessing, as the PR says, private variables: @safe @nogc pure @property { const uint linnum() { return _linnum; } const uint charnum() { return _charnum; } void linnum(uint rhs) { _linnum = rhs; } void charnum(uint rhs) { _charnum = rhs; } } ...with which the += won't work (at least this variant, as the getter isn't returning ref). Oh I see now and thanks for the information. Matheus.
idiomatic output given -preview=nosharedaccess ,
Given -preview=nosharedaccess on the command line, "hello world" fails to compile (you are referred to core.atomic ...). What is the idiomatic way to get writeln style output from a nosharedaccess program? Is separate compilation the way to go?
Re: Privatize a few members to allow messing with them #11353
On Tuesday, 30 June 2020 at 19:42:57 UTC, matheus wrote: in this case this was more a style thing than anything else right? Or is there something I'm not able to see? Before the change, linnum and charnum are public variables, one can do a += on them. After the change, they become properties accessing, as the PR says, private variables: @safe @nogc pure @property { const uint linnum() { return _linnum; } const uint charnum() { return _charnum; } void linnum(uint rhs) { _linnum = rhs; } void charnum(uint rhs) { _charnum = rhs; } } ...with which the += won't work (at least this variant, as the getter isn't returning ref).
Privatize a few members to allow messing with them #11353
Hi, I was looking the PR in DMD and I found this one: https://github.com/dlang/dmd/pull/11353/ One of the changes was: -loc.linnum += incrementLoc; +loc.linnum = loc.linnum + incrementLoc; I usually do the former and I particularly hate the later, so my question is, in this case this was more a style thing than anything else right? Or is there something I'm not able to see? Thanks, Matheus.
Re: scope guard question
On Tuesday, 30 June 2020 at 12:18:14 UTC, Steven Schveighoffer wrote: On 6/30/20 2:56 AM, Arjan wrote: On Monday, 29 June 2020 at 22:47:16 UTC, Steven Schveighoffer wrote: [...] Thanks for the assurance. The spec does state it like this: ``` The ScopeGuardStatement executes NonEmptyOrScopeBlockStatement at the close of the current scope, rather than at the point where the ScopeGuardStatement appears. ``` Which is correct, but there is no single example with a return where the ScopeBlockStatement interferes with the return. I started wondering about this since I hit a bug in a piece of code. I can see where it would be confusing, and it could probably contain an example and clarification. -steve That would certainly be helpfull.
Re: Why is this allowed
On 6/30/20 2:22 PM, H. S. Teoh wrote: On Tue, Jun 30, 2020 at 02:06:13PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: On 6/30/20 12:37 PM, Steven Schveighoffer wrote: [...] I take it back, I didn't realize this wasn't something that happened with dynamic arrays: int[] dyn = [1, 2, 3]; dyn = 5; // error dyn[] = 5; // ok, brackets required I would say that's a decent precedent to deprecate and remove that functionality. [...] Could you add this info to the bugzilla issue as additional evidence that this (mis)feature should be removed? https://issues.dlang.org/show_bug.cgi?id=15932 That's a different issue. In the case of: staticarr = 5; There is no issue with lifetime management or memory safety. It's possible that fixing 15932 would fix this issue too, but it's possible that's not true (we are assuming it's the implicit cast that is causing this issue, but it might be separately implemented). -Steve
Re: Why is this allowed
On Tue, Jun 30, 2020 at 02:06:13PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: > On 6/30/20 12:37 PM, Steven Schveighoffer wrote: [...] > I take it back, I didn't realize this wasn't something that happened > with dynamic arrays: > > int[] dyn = [1, 2, 3]; > > dyn = 5; // error > dyn[] = 5; // ok, brackets required > > I would say that's a decent precedent to deprecate and remove that > functionality. [...] Could you add this info to the bugzilla issue as additional evidence that this (mis)feature should be removed? https://issues.dlang.org/show_bug.cgi?id=15932 T -- "640K ought to be enough" -- Bill G. (allegedly), 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.
Re: Why is this allowed
On 6/30/20 12:37 PM, Steven Schveighoffer wrote: On 6/30/20 12:22 PM, JN wrote: Spent some time debugging because I didn't notice it at first, essentially something like this: int[3] foo = [1, 2, 3]; foo = 5; writeln(foo); // 5, 5, 5 Why does such code compile? I don't think this should be permitted, because it's easy to make a mistake (when you wanted foo[index] but forgot the []). If someone wants to assign a value to every element they could do foo[] = 5; instead which is explicit. That's a feature. I don't think it's going away. The problem of accidental assignment is probably not very common. I take it back, I didn't realize this wasn't something that happened with dynamic arrays: int[] dyn = [1, 2, 3]; dyn = 5; // error dyn[] = 5; // ok, brackets required I would say that's a decent precedent to deprecate and remove that functionality. -Steve
Re: Why is this allowed
On Tue, Jun 30, 2020 at 04:50:07PM +, Adam D. Ruppe via Digitalmars-d-learn wrote: > On Tuesday, 30 June 2020 at 16:41:50 UTC, JN wrote: > > I like my code to be explicit, even at a cost of some extra typing, > > rather than get bitten by some unexpected implicit behavior. > > I agree, I think ALL implicit slicing of static arrays are problematic > and should be removed. If you want to set it all or slice it for any > other reason, just put on the []. We've known this for at least 4 years, yet nothing has been done about it. :-( https://issues.dlang.org/show_bug.cgi?id=15932 The problem isn't just safety, which is partly addressed by dip1000, but also mistakes of the kind the OP posted. Basically, it's a misfeature with many ill side-effects all in the questionable name of convenience. It's time we got rid of it. T -- Truth, Sir, is a cow which will give [skeptics] no more milk, and so they are gone to milk the bull. -- Sam. Johnson
Re: Why is this allowed
On Tuesday, 30 June 2020 at 16:41:50 UTC, JN wrote: I like my code to be explicit, even at a cost of some extra typing, rather than get bitten by some unexpected implicit behavior. I agree, I think ALL implicit slicing of static arrays are problematic and should be removed. If you want to set it all or slice it for any other reason, just put on the [].
Re: Why is this allowed
On Tuesday, 30 June 2020 at 16:37:12 UTC, Steven Schveighoffer wrote: That's a feature. I don't think it's going away. The problem of accidental assignment is probably not very common. -Steve What is the benefit of this feature? I feel like D has quite a few of such "features". I like my code to be explicit, even at a cost of some extra typing, rather than get bitten by some unexpected implicit behavior.
Re: Why is this allowed
On 6/30/20 12:22 PM, JN wrote: Spent some time debugging because I didn't notice it at first, essentially something like this: int[3] foo = [1, 2, 3]; foo = 5; writeln(foo); // 5, 5, 5 Why does such code compile? I don't think this should be permitted, because it's easy to make a mistake (when you wanted foo[index] but forgot the []). If someone wants to assign a value to every element they could do foo[] = 5; instead which is explicit. That's a feature. I don't think it's going away. The problem of accidental assignment is probably not very common. -Steve
Re: Why is this allowed
On Tue, Jun 30, 2020 at 04:22:57PM +, JN via Digitalmars-d-learn wrote: > Spent some time debugging because I didn't notice it at first, > essentially something like this: > > int[3] foo = [1, 2, 3]; > foo = 5; > writeln(foo); // 5, 5, 5 > > Why does such code compile? I don't think this should be permitted, > because it's easy to make a mistake (when you wanted foo[index] but > forgot the []). If someone wants to assign a value to every element > they could do foo[] = 5; instead which is explicit. File a bug? I suspect that one potential reason is that nasty misfeature of static arrays implicitly converting to a slice of itself, so `foo = 5;` is in some sense being translated as `foo[] = 5;`. (And on that note, this implicit static -> dynamic array conversion is seriously a nasty misfeature that ought to be killed with fire. It leads to bugs like this: struct Database { int[] data; void set(int[] _data) { data = _data; } } void myFunc(ref Database db) { int[3] x; db.set(x); // oops } ) T -- Once the bikeshed is up for painting, the rainbow won't suffice. -- Andrei Alexandrescu
Why is this allowed
Spent some time debugging because I didn't notice it at first, essentially something like this: int[3] foo = [1, 2, 3]; foo = 5; writeln(foo); // 5, 5, 5 Why does such code compile? I don't think this should be permitted, because it's easy to make a mistake (when you wanted foo[index] but forgot the []). If someone wants to assign a value to every element they could do foo[] = 5; instead which is explicit.
Re: How to implement Canceleable spawn() from parent
On 6/30/20 10:15 AM, Simen Kjærås wrote: On Tuesday, 30 June 2020 at 13:44:38 UTC, aberba wrote: On Tuesday, 30 June 2020 at 12:48:32 UTC, Simen Kjærås wrote: On Tuesday, 30 June 2020 at 08:15:54 UTC, aberba wrote: On Tuesday, 30 June 2020 at 00:33:41 UTC, Ali Çehreli wrote: On 6/29/20 4:34 PM, aberba wrote: > So with this, without the Thread.sleep() to block main from exiting, the > spawned thread will terminate immediately. You can call core.thread.thread_joinAll at the end of main. So I tried that initially but my (){ writeln(...) } wasn't printing anything in console. Could that be related to stdout buffering? The program kept running though. So I guess the error is elsewhere, but I'm not sure where and how. Yeah, you're right. I changed receiveTimeout() to receive() to try something and forgot to change it back. Jeez, I hate myself. Thanks. So how can I now hide the core.thread.thread_joinAll so the library user doesn't have to type it themselves in main() ? I don't see how that can be done. __gshared Tid mainTid; static this() { if (mainTid.tupleof[0] is null) { mainTid = thisTid; } } static ~this() { if (thisTid == mainTid) { thread_joinAll(); } } First, you can just use shared static dtor, as this runs once at the end of the program. At the very least, you can run the setting of mainTid in a shared constructor to avoid the race conditions (also no need to check if its set already). Second, I realized, thread_joinAll is already being done by the runtime: https://github.com/dlang/druntime/blob/67618bd2dc8905ad5dee95f3329109aebd839b74/src/rt/dmain2.d#L226 So the question really becomes -- why is it necessary to call thread_joinAll in main? It's because the main thread's TLS static destructor is closing the owner mailbox, which is sending a message to all the threads that the owner is terminated, causing your threads to exit immediately. See here: https://github.com/dlang/phobos/blob/268b56be494cc4f76da54a66a6960fa7e527c4ed/std/concurrency.d#L223 Honestly though, I think this is the correct behavior -- if you exit main, you are expecting the program to not hang indefinitely. -Steve
Re: How to implement Canceleable spawn() from parent
On Tuesday, 30 June 2020 at 13:44:38 UTC, aberba wrote: On Tuesday, 30 June 2020 at 12:48:32 UTC, Simen Kjærås wrote: On Tuesday, 30 June 2020 at 08:15:54 UTC, aberba wrote: On Tuesday, 30 June 2020 at 00:33:41 UTC, Ali Çehreli wrote: On 6/29/20 4:34 PM, aberba wrote: > So with this, without the Thread.sleep() to block main from exiting, the > spawned thread will terminate immediately. You can call core.thread.thread_joinAll at the end of main. So I tried that initially but my (){ writeln(...) } wasn't printing anything in console. Could that be related to stdout buffering? The program kept running though. So I guess the error is elsewhere, but I'm not sure where and how. Yeah, you're right. I changed receiveTimeout() to receive() to try something and forgot to change it back. Jeez, I hate myself. Thanks. So how can I now hide the core.thread.thread_joinAll so the library user doesn't have to type it themselves in main() ? I don't see how that can be done. __gshared Tid mainTid; static this() { if (mainTid.tupleof[0] is null) { mainTid = thisTid; } } static ~this() { if (thisTid == mainTid) { thread_joinAll(); } } The above code does the trick. So, what does it do? __gshared means 'this variable is accessible to all threads'. static this() runs upon creation of any thread including the main thread. Since the main thread will run first*, it gets to store its Tid in mainTid, and every other thread will see a populated mainTid and leave it alone. In the module destructor, which runs after main(), we call thread_joinAll() iff we're the main thread. Now, why should you not do this? Well first, instead of getting a tidy crash you get a process that doesn't end. Second, there's the race conditions described below. Third, there's the principle of least astonishment. D programmers expect that when main() returns, the program will exit shortly(ish), while this zombie could continue running indefinitely. -- Simen *I'm pretty sure this is possibly wrong, if a module constructor spawns a new thread. There's also a possible race condition where newly spawned modules may conceivably not see a properly initialized mainTid.
Re: How to implement Canceleable spawn() from parent
On 6/30/20 9:44 AM, aberba wrote: On Tuesday, 30 June 2020 at 12:48:32 UTC, Simen Kjærås wrote: So I guess the error is elsewhere, but I'm not sure where and how. Yeah, you're right. I changed receiveTimeout() to receive() to try something and forgot to change it back. Jeez, I hate myself. Thanks. So how can I now hide the core.thread.thread_joinAll so the library user doesn't have to type it themselves in main() ? I don't see how that can be done. I assume you need something more than thread_joinAll, because you need to stop all the threads from executing also. So wrapping this up into a single call would be what you use (it's OK to ask the user to clean up a library manually). -Steve
Re: How to implement Canceleable spawn() from parent
On Tuesday, 30 June 2020 at 12:48:32 UTC, Simen Kjærås wrote: On Tuesday, 30 June 2020 at 08:15:54 UTC, aberba wrote: On Tuesday, 30 June 2020 at 00:33:41 UTC, Ali Çehreli wrote: On 6/29/20 4:34 PM, aberba wrote: > So with this, without the Thread.sleep() to block main from exiting, the > spawned thread will terminate immediately. You can call core.thread.thread_joinAll at the end of main. So I tried that initially but my (){ writeln(...) } wasn't printing anything in console. Could that be related to stdout buffering? The program kept running though. So I guess the error is elsewhere, but I'm not sure where and how. Yeah, you're right. I changed receiveTimeout() to receive() to try something and forgot to change it back. Jeez, I hate myself. Thanks. So how can I now hide the core.thread.thread_joinAll so the library user doesn't have to type it themselves in main() ? I don't see how that can be done.
Re: Calling C functions
On Tuesday, 30 June 2020 at 12:22:15 UTC, Steven Schveighoffer wrote: (i.e. one cannot use extern(D) functions for C callbacks). I don't think that's a big issue. Honestly, I don't think it's an issue at all. BTW, the order of arguments is not the only thing. Variadic functions in D and C are completely different. I don't think it's possible to implement a C style variadic function with D linkage (the language doesn't provide a syntax for it). There's also D specific types which C cannot handle (like arrays and delegates). I'm sure there are other differences in the ABIs. -- /Jacob Carlborg
Re: How to implement Canceleable spawn() from parent
On Tuesday, 30 June 2020 at 08:15:54 UTC, aberba wrote: On Tuesday, 30 June 2020 at 00:33:41 UTC, Ali Çehreli wrote: On 6/29/20 4:34 PM, aberba wrote: > So with this, without the Thread.sleep() to block main from exiting, the > spawned thread will terminate immediately. You can call core.thread.thread_joinAll at the end of main. So I tried that initially but my (){ writeln(...) } wasn't printing anything in console. Could that be related to stdout buffering? The program kept running though. Seems weird. This works great on my machine: import core.time : Duration, msecs; import core.thread : Thread, thread_joinAll; import std.concurrency : spawn, Tid, send, receiveTimeout; import std.stdio : writeln; private struct IntervalStop {} Tid setInterval(Duration dur, void function() fn) { return spawn((Duration d, void function() f){ while (!receiveTimeout(d, (IntervalStop s){})) { f(); } }, dur, fn); } void stopInterval(Tid tid) { tid.send(IntervalStop()); } void main() { auto a = setInterval(1000.msecs, (){ writeln("Hello from spawned thread A"); }); // Stop it before it happens stopInterval(a); Thread.sleep(2000.msecs); auto b = setInterval(1000.msecs, (){ writeln("Hello from spawned thread B"); }); // Let this one run a little Thread.sleep(2500.msecs); stopInterval(b); auto c = setInterval(1000.msecs, (){ writeln("Hello from spawned thread C"); }); // Sending the wrong message doesn't make it happen or stop prematurely c.send("Stop this at once!"); Thread.sleep(2500.msecs); stopInterval(c); thread_joinAll(); } So I guess the error is elsewhere, but I'm not sure where and how. -- Simen
Re: Calling C functions
On 6/30/20 3:00 AM, Kagamin wrote: On Monday, 29 June 2020 at 19:55:59 UTC, Steven Schveighoffer wrote: Yep, for sure. I'll file an issue. Anyone know why the calling convention would differ? It's easier to enforce left to right evaluation order this way: arguments are pushed to stack as they are evaluated, which is pascal calling convention. Easier, or more efficient? The cost seems high if it doesn't provide any efficiency benefits (i.e. one cannot use extern(D) functions for C callbacks). In any case, I filed an issue: https://issues.dlang.org/show_bug.cgi?id=20993 -Steve
Re: scope guard question
On 6/30/20 2:56 AM, Arjan wrote: On Monday, 29 June 2020 at 22:47:16 UTC, Steven Schveighoffer wrote: Yes. The return statement is inside the scope of the function, so it runs before the scope is exited. Are you saying the spec doesn't say that? Thanks for the assurance. The spec does state it like this: ``` The ScopeGuardStatement executes NonEmptyOrScopeBlockStatement at the close of the current scope, rather than at the point where the ScopeGuardStatement appears. ``` Which is correct, but there is no single example with a return where the ScopeBlockStatement interferes with the return. I started wondering about this since I hit a bug in a piece of code. I can see where it would be confusing, and it could probably contain an example and clarification. -steve
Re: How to implement Canceleable spawn() from parent
On Tuesday, 30 June 2020 at 00:33:41 UTC, Ali Çehreli wrote: On 6/29/20 4:34 PM, aberba wrote: > So with this, without the Thread.sleep() to block main from exiting, the > spawned thread will terminate immediately. You can call core.thread.thread_joinAll at the end of main. So I tried that initially but my (){ writeln(...) } wasn't printing anything in console. Could that be related to stdout buffering? The program kept running though. Another way would be to wait for a worker's exit by looking for LinkTerminated but you need to start the thread with spawnLinked: Read that too, but doesn't seem like the desired behavior I want. So here's the thing, unlike JavaScript, the D behavior seems to be like a while(bool){} has to be placed directly within the scope of main. Was thinking as long my while loop in setInterval() was running, spawn() will be kept alive. It seem both vibe.d and arsd have a similar setInterval() implementation and they both require using their event loop to keep the program alive. In my case, wanted setInterval() to behave like it's own event loop without placing it in a while(bool){} loop in main()
Re: Calling C functions
On Monday, 29 June 2020 at 19:55:59 UTC, Steven Schveighoffer wrote: Yep, for sure. I'll file an issue. Anyone know why the calling convention would differ? It's easier to enforce left to right evaluation order this way: arguments are pushed to stack as they are evaluated, which is pascal calling convention.
Re: scope guard question
On Monday, 29 June 2020 at 22:47:16 UTC, Steven Schveighoffer wrote: Yes. The return statement is inside the scope of the function, so it runs before the scope is exited. Are you saying the spec doesn't say that? Thanks for the assurance. The spec does state it like this: ``` The ScopeGuardStatement executes NonEmptyOrScopeBlockStatement at the close of the current scope, rather than at the point where the ScopeGuardStatement appears. ``` Which is correct, but there is no single example with a return where the ScopeBlockStatement interferes with the return. I started wondering about this since I hit a bug in a piece of code.
Re: Garbage collection
On Saturday, 27 June 2020 at 14:49:34 UTC, James Gray wrote: I have produced something which essentially reproduces my problem. What is the problem? Do you have a leak or you want to know how GC works?