Re: Program exited with code -11 when calling

2020-06-30 Thread Kagamin via Digitalmars-d-learn
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

2020-06-30 Thread Anthony via Digitalmars-d-learn

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

2020-06-30 Thread Anthony via Digitalmars-d-learn

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

2020-06-30 Thread Anthony via Digitalmars-d-learn

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

2020-06-30 Thread H. S. Teoh via Digitalmars-d-learn
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

2020-06-30 Thread Cym13 via Digitalmars-d-learn

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

2020-06-30 Thread Anthony via Digitalmars-d-learn

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

2020-06-30 Thread tastyminerals via Digitalmars-d-learn

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 ,

2020-06-30 Thread Bruce Carneal via Digitalmars-d-learn

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

2020-06-30 Thread matheus via Digitalmars-d-learn

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 ,

2020-06-30 Thread Stanislav Blinov via Digitalmars-d-learn
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 ,

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread Stanislav Blinov via Digitalmars-d-learn

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

2020-06-30 Thread matheus via Digitalmars-d-learn

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

2020-06-30 Thread matheus via Digitalmars-d-learn

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 ,

2020-06-30 Thread Bruce Carneal via Digitalmars-d-learn
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

2020-06-30 Thread Stanislav Blinov via Digitalmars-d-learn

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

2020-06-30 Thread matheus via Digitalmars-d-learn
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

2020-06-30 Thread Arjan via Digitalmars-d-learn
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

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread H. S. Teoh via Digitalmars-d-learn
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

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread H. S. Teoh via Digitalmars-d-learn
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

2020-06-30 Thread Adam D. Ruppe via Digitalmars-d-learn

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

2020-06-30 Thread JN via Digitalmars-d-learn
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

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread H. S. Teoh via Digitalmars-d-learn
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

2020-06-30 Thread JN via Digitalmars-d-learn
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

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread Simen Kjærås via Digitalmars-d-learn

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

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread aberba via Digitalmars-d-learn

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

2020-06-30 Thread Jacob Carlborg via Digitalmars-d-learn
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

2020-06-30 Thread Simen Kjærås via Digitalmars-d-learn

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

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-06-30 Thread aberba via Digitalmars-d-learn

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

2020-06-30 Thread Kagamin via Digitalmars-d-learn
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

2020-06-30 Thread Arjan via Digitalmars-d-learn
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

2020-06-30 Thread Kagamin via Digitalmars-d-learn

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?