Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn
On Thursday, 23 September 2021 at 20:32:36 UTC, james.p.leblanc 
wrote:
On Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc 
wrote:
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 2:20 PM, james.p.leblanc wrote:


```
Produces:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z5): question.main.MapResult!(__lambda2, 
JSONValue[]).MapResult, z5: [true, false, true]

z5: [true, false, true]



Sigh ... my suggested "minor edit" above produces a "map result" 
instead of
the desired native array ... here is the **fix** by appending 
".array" at the
end (which is the suffix Steve originally offered).  The 
following gives

the desired **bool[]** result.

```d
import std.array;

   auto z5 = jj["ba"].array.map!(v => v.get!bool).array;
   writeln("typeid(z5): ", typeid(z5), ", z5: ", z5);
   writeln("z5: ", z5);
```

Regards,
James





Re: associative array with element type struct ?

2021-09-23 Thread Paul via Digitalmars-d-learn

Of course! And it's very common. <= lol


Thanks Ali.  Much appreciated!






Re: associative array with element type struct ?

2021-09-23 Thread Ali Çehreli via Digitalmars-d-learn

On 9/23/21 3:06 PM, Paul wrote:
> Can I have an associative array with the element type being a struct?

Of course! And it's very common. :)

> ...this
> 26  // simple dual tone key struct
> 27  struct keytones { ushort rowFreq; ushort colFreq; }
> 28
> 29  // keypad associative array
> 30  keytones[string] keypad;
> 31  keypad["1"].rowFreq = 697; keypad["1"].colFreq = 1209;
>
> gets this response from DMD compiler
>
> aaa.d(30): Error: undefined identifier `keypad`

I think you got that error from a different experiment because 'keypad' 
is clearly valid in that code. However, you are attempting to access 
members of a non-existing element: There is no element corresponding to 
"1" in the AA (yet).


There are multiple ways of populating an AA but I usually and simply 
assign an rvalue in such cases:


void main() {
  // simple dual tone key struct
  struct keytones { ushort rowFreq; ushort colFreq; }

  // keypad associative array
  keytones[string] keypad;
  keypad["1"] = keytones(697, 1209);
}

Ali



associative array with element type struct ?

2021-09-23 Thread Paul via Digitalmars-d-learn
Can I have an associative array with the element type being a 
struct?

..this
26  // simple dual tone key struct
27  struct keytones { ushort rowFreq; ushort colFreq; }
28
29  // keypad associative array
30  keytones[string] keypad;
31  keypad["1"].rowFreq = 697; keypad["1"].colFreq = 1209;

...gets this response from DMD compiler

aaa.d(30): Error: undefined identifier `keypad`
aaa.d(30): Error: declaration `aaa.main.keytones` is already 
defined

aaa.d(27):`struct` `keytones` is defined here

thanks for any assistance!


Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn
On Thursday, 23 September 2021 at 19:18:11 UTC, james.p.leblanc 
wrote:
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 2:20 PM, james.p.leblanc wrote:

Dear D-ers,



Here comes a minor update (small rearrangement in mapping/array 
ordering)
for anyone who may be interested.  With this small edit to the 
suggested code,

it works just fine!  Here:


 ```d

   auto z5 = jj["ba"].array.map!(v => v.get!bool);

   writeln("typeid(z5): ", typeid(z5), ", z5: ", z5);
   writeln("z5: ", z5);

```
Produces:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z5): question.main.MapResult!(__lambda2, 
JSONValue[]).MapResult, z5: [true, false, true]

z5: [true, false, true]


Cheers,
James




Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn

On Thursday, 23 September 2021 at 19:32:12 UTC, eugene wrote:

C (more elaborated) variant:
http://zed.karelia.ru/mmedia/bin/edsm-g2-rev-h.tar.gz


Sound, GUI? Easy, see
http://zed.karelia.ru/mmedia/bin/xjiss4.tar.gz
It's computer keyboard 'piano', based on the same engine.

As I've already mentioned, I was inspired several years ago
by very nice book, 'Modeling Software with Finite State Machines: 
A Practical Approach'

by Wagner F. et al.

I applied some ideas from the book to Posix/Linux API and
developed EDSM - 'Event driven state machines' - and since I
do not need no libev, libevent and alike.

State machines per se are very powerful methodology
to model program behavior. Also notice,
that machines communicates with each other
by messages - remember Alan Key main OOP principle?
It's message exchange, not class hierarchy (inheritance 
blah-blah-blah).


As to client-server echo pair in D, it is my 3rd (and most 
successful!!!)

attempt to re-implement EDSM in some 'modern' language.

Initially my criteria for choosing a lang were:

- compiles to native code, goodby Java
- no garbage collector, goodby almost all :)
- no classes, only interfaces.
- maybe, something else, do not remember

The only language, that fit to my initial desires, was Rust.
But borrow checker (and especially <'a>, expicite lifetimes)
appeared to be the real hell for me. One can use raw pointers
instead of references, but then your code is from head to toe
is in unsafe {} blocks.

Next one was (just accidentally) was c#.
Here, I was not be able to make signals work properly and I 
dropped it.


After reading some texts a la 'alternatives to c++',
I decided to try D, despite it's 'unpopularity'.





Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 18:53:25 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 1:44 PM, eugene wrote:

Just a note: there is no 'signal handler' in the program.
SIGINT/SIGTERM are **blocked**, notifications (POLLIN) are 
received via epoll_wait().


Oh interesting! I didn't read the code closely enough.


"everything in Unix is a file" (c)

All event sources (sockets, timers, signal, file system events)
can be 'routed' through i/o multiplexing facilities, like
select/poll(posix)/epoll(linux)/queue(freebsd) etc.

Probably, a destructor for Signal class should be added, in 
which


Yes, I would recommend that. Always good for a destructor to 
clean up any non-GC resources that haven't already been cleaned 
up. That's actually what class destructors are for.


No, destructors are not necessary, since after SIGINT/SIRTERM
program is about to terminate and all resources will be
released anyway.

In C I do same way - do not close fd, which live from
start to end, do not free() pointers and so on, no need.


So it gets written to the file descriptor instead?


When signal happens (or timer expires, or file is deleted)
process get EPOLLIN on corresponding file descriptor
via epoll_wait() and then process has to read some info
from these file descriptors.

And nobody is there reading it, so it's just closed along with 
the process?


Yes, as any other file descriptor.

I've not done signals this way, it seems pretty clever and less 
prone to asynchronous issues.


It's just great, thanks to Linux kernel developers.
Look in to engine dir in the source.

C (more elaborated) variant:
http://zed.karelia.ru/mmedia/bin/edsm-g2-rev-h.tar.gz




Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn
On Thursday, 23 September 2021 at 19:04:47 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 2:20 PM, james.p.leblanc wrote:

Dear D-ers,

In attempting to cast JSONValues that hold arrays to "native"



How you really do this:

```d
import std.algorithm : map;
auto z5 = jj["ba"] // get the JSONValue that is at the key "ba"
  .map!(v => v.get!bool) // map each value into a boolean
  .array // create an array out of the results;
assert z5 == [true, false, true];
```

(warning, untested)

-Steve


Steve,

Your thorough explanations have helped me understand quite much.
Thank you for your energy and patience in these forum 
contributions.


In fact, I had begun to think that "map", may be what was needed 
here
and I had made a few naive attempts ... but this did not go so 
well.
With your suggested solution, I believe I can make headway on 
this.


Thanks Again,
James




Re: Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 2:20 PM, james.p.leblanc wrote:

Dear D-ers,

In attempting to cast JSONValues that hold arrays to "native" array types,
I have hit some issues.  Example code:

```d
import std.stdio;
import std.json;

void main(){

    JSONValue jj;
    jj["d"] = [ 1.234 ];  // a "dummy" double value
    jj["ba"] = [ true, false, true];  // "ba" boolean array


Note that this creates a JSONValue array which *copies* the values of 
the boolean array, converting them to JSONValue (which is what a 
JSONValue array stores).




    writeln("typeid(jj): ", typeid(jj), ", jj: ", jj );

    // various things that I thought might work, but do NOT

    auto z1 = cast(bool)   jj["ba"];   // attempt #1


A JSONValue cannot be cast to a boolean (it does not provide the 
appropriate opCast)



    auto z2 = cast(bool[]) jj["ba"];   // attempt #2
    auto z3 = cast(bool)   jj["ba"].array; // attempt #3


These try to cast something that is not an array to an array or vice 
versa. These are not supported unless the type itself has an `opCast` 
overload.



    auto z4 = cast(bool[]) jj["ba"].array; // attempt #4


Casting one array type to another is like pointing at the array that 
represents the original type *as if* it were of the new type. No 
translation is made, you are pointing at the same memory! The length is 
adjusted based on the size of the original array element and the size of 
the new one.


For instance:

```d
int[] arr = [1];
auto a2 = cast(ubyte[])arr;

assert(a2.length == 4);
assert(a2 == cast(ubyte[])([1, 0, 0, 0])); // assuming little endian
```



However, if I comment out the offending attempts (1, 2, and 3), then it
compiles, and can run ... but produces a result which I very much do NOT
understand:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z4): bool[], z4: [false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, false, 
true, false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, false, 
false, false, false, false, true, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, true, false, 
false, false, false, false, false, false]


This is an array of JSONValue, with each byte interpreted as if it were 
a bool.



H... is there a standard way to push these JSONValues into nice native
array types? (The real code is eventually going to be using traits and 
mixins

... but I do not think this should pose additional problems).


How you really do this:

```d
import std.algorithm : map;
auto z5 = jj["ba"] // get the JSONValue that is at the key "ba"
  .map!(v => v.get!bool) // map each value into a boolean
  .array // create an array out of the results;
assert z5 == [true, false, true];
```

(warning, untested)

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 1:44 PM, eugene wrote:

On Thursday, 23 September 2021 at 17:20:18 UTC, Steven Schveighoffer wrote:

So imagine the sequence:


With ease!


1. ctrl-c, signal handler triggers, shutting down the loop


Just a note: there is no 'signal handler' in the program.
SIGINT/SIGTERM are **blocked**, notifications (POLLIN) are received via 
epoll_wait().


Oh interesting! I didn't read the code closely enough.




2. main exits
3. GC finalizes all objects, including the Stopper and it's members


Probably, a destructor for Signal class should be added, in which

- close fd, obtained from signalfd()
- unblock the signal (thus default signal handler is back again)


Yes, I would recommend that. Always good for a destructor to clean up 
any non-GC resources that haven't already been cleaned up. That's 
actually what class destructors are for.




4. ctrl-c happens again, but you didn't unregister the signal handler, 
so it's run again, referencing the now-deleted object.


At this point we have default signal handler


5. segfault
It's theoretically a very very small window.


But even without destructor, no segfault will happen,
because **there is no signal handler**


So it gets written to the file descriptor instead? And nobody is there 
reading it, so it's just closed along with the process?


I've not done signals this way, it seems pretty clever and less prone to 
asynchronous issues.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 18:43:36 UTC, Steven 
Schveighoffer wrote:
With dmd -O -inline, there is a chance it will be collected. 
Inlining is key here.


never mind, GC.addRoot() looks more trustworthy, anyway :)



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 2:18 PM, eugene wrote:

On Thursday, 23 September 2021 at 17:16:23 UTC, Steven Schveighoffer wrote:

On 9/23/21 12:58 PM, eugene wrote:
On Thursday, 23 September 2021 at 15:56:16 UTC, Steven Schveighoffer 
wrote:

See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks 





"
This method references the obj parameter, making that object 
ineligible for garbage collection from the start of the routine to 
the point, in execution order, where this method is called. Code this 
method at the end, not the beginning, of the range of instructions 
where obj must be available.

"

**Code this method at the end...**

:)
it is the same as proposed by jfondren simple
writeln(stopper.sg0.number) in the end of main, right?


Same effect, but writeln actually executes code to write data to the 
console, whereas KeepAlive doesn't do anything.


```d
void keepAlive(Object o) {
}

void main(string[] args) {

     import core.memory : GC;

     auto Main = new Main();
     Main.run();

     auto stopper = new Stopper();
     stopper.run();

     writeln(" === Hello, world! === ");
     auto md = new MessageDispatcher();
     md.loop();

     keepAlive(Main);
     keepAlive(stopper);

     writeln(" === Goodbye, world! === ");
}
```
works ok with dmd, stopper is not collected.


With dmd -O -inline, there is a chance it will be collected. Inlining is 
key here.


-Steve


Casting JSONValues arrays to native arrays ... ??? ...

2021-09-23 Thread james.p.leblanc via Digitalmars-d-learn

Dear D-ers,

In attempting to cast JSONValues that hold arrays to "native" 
array types,

I have hit some issues.  Example code:

```d
import std.stdio;
import std.json;

void main(){

   JSONValue jj;
   jj["d"] = [ 1.234 ];  // a "dummy" double value
   jj["ba"] = [ true, false, true];  // "ba" boolean array

   writeln("typeid(jj): ", typeid(jj), ", jj: ", jj );

   // various things that I thought might work, but do NOT

   auto z1 = cast(bool)   jj["ba"];   // attempt #1
   auto z2 = cast(bool[]) jj["ba"];   // attempt #2
   auto z3 = cast(bool)   jj["ba"].array; // attempt #3
   auto z4 = cast(bool[]) jj["ba"].array; // attempt #4
   writeln("typeid(z4): ", typeid(z4), ", z4: ", z4 );

}
```
Attempts 1,2, and 3 yield compilation errors (which I somewhat 
understand):


question.d(12): Error: cannot cast expression `jj.opIndex("ba")` 
of type `JSONValue` to `bool`
question.d(13): Error: cannot cast expression `jj.opIndex("ba")` 
of type `JSONValue` to `bool[]`
question.d(14): Error: cannot cast expression 
`jj.opIndex("ba").array()` of type `JSONValue[]` to `bool`


However, if I comment out the offending attempts (1, 2, and 3), 
then it
compiles, and can run ... but produces a result which I very much 
do NOT

understand:

typeid(jj): std.json.JSONValue, jj: 
{"ba":[true,false,true],"d":[1.23399]}
typeid(z4): bool[], z4: [false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, 
false, false, true, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, true, 
false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, false, false, false, false, 
false, false, false, false, false, true, false, false, false, 
false, false, false, false]


H... is there a standard way to push these JSONValues into 
nice native
array types? (The real code is eventually going to be using 
traits and mixins

... but I do not think this should pose additional problems).

All help and illumination thankfully received.
Best Regards,
James







Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 17:16:23 UTC, Steven 
Schveighoffer wrote:

On 9/23/21 12:58 PM, eugene wrote:
On Thursday, 23 September 2021 at 15:56:16 UTC, Steven 
Schveighoffer wrote:

See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks



"
This method references the obj parameter, making that object 
ineligible for garbage collection from the start of the 
routine to the point, in execution order, where this method is 
called. Code this method at the end, not the beginning, of the 
range of instructions where obj must be available.

"

**Code this method at the end...**

:)
it is the same as proposed by jfondren simple
writeln(stopper.sg0.number) in the end of main, right?


Same effect, but writeln actually executes code to write data 
to the console, whereas KeepAlive doesn't do anything.


```d
void keepAlive(Object o) {
}

void main(string[] args) {

import core.memory : GC;

auto Main = new Main();
Main.run();

auto stopper = new Stopper();
stopper.run();

writeln(" === Hello, world! === ");
auto md = new MessageDispatcher();
md.loop();

keepAlive(Main);
keepAlive(stopper);

writeln(" === Goodbye, world! === ");
}
```
works ok with dmd, stopper is not collected.




Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn

On Thursday, 23 September 2021 at 17:53:00 UTC, eugene wrote:

On Thursday, 23 September 2021 at 17:49:43 UTC, eugene wrote:
On Thursday, 23 September 2021 at 17:20:18 UTC, Steven 
Schveighoffer wrote:

1. ctrl-c, signal handler triggers, shutting down the loop
2. main exits
3. GC finalizes all objects, including the Stopper and it's 
members


but both SIGINT and SIGTERM are still **blocked**,
they just will not reach the process.


oops..


no oops, that's all right.

- when creating Signal instance, corresponding signal becames 
blocked


```d
final class Signal : EventSource {

enum int sigInt = SIGINT;
enum int sigTerm = SIGTERM;
ulong number;

this(int signo) {
super('S');

sigset_t sset;
sigset_t old_sset;
/* block the signal */
sigemptyset();
sigaddset(, signo);
sigprocmask(SIG_BLOCK, , _sset);

id = signalfd(-1, , SFD_CLOEXEC);
```
- upon receiving SIGINT stopperIdleS0() is called.
now stop variable of EventQueue is false

- next call to wait() method just return.
(remember, signals are still blocked)






Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn

On Thursday, 23 September 2021 at 17:49:43 UTC, eugene wrote:
On Thursday, 23 September 2021 at 17:20:18 UTC, Steven 
Schveighoffer wrote:

1. ctrl-c, signal handler triggers, shutting down the loop
2. main exits
3. GC finalizes all objects, including the Stopper and it's 
members


but both SIGINT and SIGTERM are still **blocked**,
they just will not reach the process.


oops..

closing epoll fd should be moved from EventQueue dtor to stop() 
method,

then everything will be Ok.



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 17:20:18 UTC, Steven 
Schveighoffer wrote:

1. ctrl-c, signal handler triggers, shutting down the loop
2. main exits
3. GC finalizes all objects, including the Stopper and it's 
members


but both SIGINT and SIGTERM are still **blocked**,
they just will not reach the process.



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 17:20:18 UTC, Steven 
Schveighoffer wrote:

So imagine the sequence:


With ease!


1. ctrl-c, signal handler triggers, shutting down the loop


Just a note: there is no 'signal handler' in the program.
SIGINT/SIGTERM are **blocked**, notifications (POLLIN) are 
received via epoll_wait().



2. main exits
3. GC finalizes all objects, including the Stopper and it's 
members


Probably, a destructor for Signal class should be added, in which

- close fd, obtained from signalfd()
- unblock the signal (thus default signal handler is back again)

4. ctrl-c happens again, but you didn't unregister the signal 
handler, so it's run again, referencing the now-deleted object.


At this point we have default signal handler


5. segfault
It's theoretically a very very small window.


But even without destructor, no segfault will happen,
because **there is no signal handler**





Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 12:53 PM, eugene wrote:

On Thursday, 23 September 2021 at 15:53:37 UTC, Steven Schveighoffer wrote:
Technically, they should live past the end of main, because it's still 
possible to receive signals then.


No, as soon as an application get SIGTERM/SIGINT,
event queue is stopped and we do not need no
more notifications from OS (POLLIN/POLLOUT I mean).

Stopping event queue in this case is just
closing file descriptor obtained from epoll_create().
After this getting POLLIN from any fd (including signal fd) is
just impossible.




That's not what is triggering the segfault though. The segfault is 
triggered by the signal handler referencing the destroyed object.


So imagine the sequence:

1. ctrl-c, signal handler triggers, shutting down the loop
2. main exits
3. GC finalizes all objects, including the Stopper and it's members
4. ctrl-c happens again, but you didn't unregister the signal handler, 
so it's run again, referencing the now-deleted object.

5. segfault

It's theoretically a very very small window.

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 12:58 PM, eugene wrote:

On Thursday, 23 September 2021 at 15:56:16 UTC, Steven Schveighoffer wrote:

See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks 



"
This method references the obj parameter, making that object ineligible 
for garbage collection from the start of the routine to the point, in 
execution order, where this method is called. Code this method at the 
end, not the beginning, of the range of instructions where obj must be 
available.

"

**Code this method at the end...**

:)
it is the same as proposed by jfondren simple
writeln(stopper.sg0.number) in the end of main, right?


Same effect, but writeln actually executes code to write data to the 
console, whereas KeepAlive doesn't do anything.


Essentially, you get the side effect of keeping the object as live, 
without paying the penalty of inserting frivolous code.


All my efforts to achieve the same via a library were thwarted by at 
least LDC (whose optimizer is very good).


The only possible solution I can think of is to generate an opaque 
function that LDC cannot see into, in order to force it to avoid 
inlining, and have that function do nothing.


However, there's always Link-Time-Optmization...

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 15:56:16 UTC, Steven 
Schveighoffer wrote:

See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks


"
This method references the obj parameter, making that object 
ineligible for garbage collection from the start of the routine 
to the point, in execution order, where this method is called. 
Code this method at the end, not the beginning, of the range of 
instructions where obj must be available.

"

**Code this method at the end...**

:)
it is the same as proposed by jfondren simple
writeln(stopper.sg0.number) in the end of main, right?





Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 15:53:37 UTC, Steven 
Schveighoffer wrote:
Technically, they should live past the end of main, because 
it's still possible to receive signals then.


No, as soon as an application get SIGTERM/SIGINT,
event queue is stopped and we do not need no
more notifications from OS (POLLIN/POLLOUT I mean).

Stopping event queue in this case is just
closing file descriptor obtained from epoll_create().
After this getting POLLIN from any fd (including signal fd) is
just impossible.




Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 9:18 AM, eugene wrote:

On Thursday, 23 September 2021 at 12:53:14 UTC, Steven Schveighoffer wrote:



We need to add a better way to do that (similar to C# KeepAlive).


Do you mean some function attribute?..



C# KeepAlive (and Go KeepAlive) are a mechanism to do exactly what you 
suggested -- use the object later.


However, they are recognized by the compiler as an intrinsic which 
generates no code or side effects, but is not subject to elimination by 
the optimizer.


See more details:

https://docs.microsoft.com/en-us/dotnet/api/system.gc.keepalive?view=net-5.0#remarks

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 10:55 AM, eugene wrote:

On Thursday, 23 September 2021 at 14:31:34 UTC, jfondren wrote:
Nice. I thought of GC.addRoot several times but I was distracted by 
the general solution of using object lifetimes with it, so that a 
struct's destructor would call GC.removeRoot. For your case just 
pinning these and forgetting about them is the easiest way to do it.


Yes, these two must live until the end of main().
Moreover, in real (C) programs I (usually) do
not create state machines on the fly,
instead I keep them in pools, like RX/TX machines pools
in echo-server and in echo-client.



Technically, they should live past the end of main, because it's still 
possible to receive signals then.


But the chances of someone hitting ctrl-c in that window are quite small.

-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn

On Thursday, 23 September 2021 at 14:31:34 UTC, jfondren wrote:
Nice. I thought of GC.addRoot several times but I was 
distracted by the general solution of using object lifetimes 
with it, so that a struct's destructor would call 
GC.removeRoot. For your case just pinning these and forgetting 
about them is the easiest way to do it.


Yes, these two must live until the end of main().
Moreover, in real (C) programs I (usually) do
not create state machines on the fly,
instead I keep them in pools, like RX/TX machines pools
in echo-server and in echo-client.



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn

On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote:
And the most strange thing is this - if using gdc with -Os 
flag, the program behaves
exactly as when compiled with fresh dmd - destructors for sg0 
and sg1 are called soon after program start.


Now I guess, gdc optimization by size imply DSE.



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread jfondren via Digitalmars-d-learn

On Thursday, 23 September 2021 at 14:23:40 UTC, eugene wrote:

On Thursday, 23 September 2021 at 14:00:30 UTC, eugene wrote:


For the moment I am personally quite happy


```d
void main(string[] args) {

import core.memory : GC;

auto Main = new Main();
GC.addRoot(cast(void*)Main);
Main.run();

auto stopper = new Stopper();
GC.addRoot(cast(void*)stopper);
stopper.run();
```

Fine, works!


Nice. I thought of GC.addRoot several times but I was distracted 
by the general solution of using object lifetimes with it, so 
that a struct's destructor would call GC.removeRoot. For your 
case just pinning these and forgetting about them is the easiest 
way to do it.


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn

On Thursday, 23 September 2021 at 14:00:30 UTC, eugene wrote:


For the moment I am personally quite happy


```d
void main(string[] args) {

import core.memory : GC;

auto Main = new Main();
GC.addRoot(cast(void*)Main);
Main.run();

auto stopper = new Stopper();
GC.addRoot(cast(void*)stopper);
stopper.run();
```

Fine, works!



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread jfondren via Digitalmars-d-learn

On Thursday, 23 September 2021 at 13:30:42 UTC, eugene wrote:

So, in C it is MY (potentially wrong) code.
In D, it is NOT MY code, it is GC.


Actually in both cases it is MY+the compiler's code. A very 
similar example from C-land (without my digging up the exact 
details) is something like


```c
for (int i = 0; i >= 0; i++) {
  // exit loop on signed integer overflow
}
```

where gcc 2.95 would do what "MY code" said, but later gcc 
versions would 'optimize' into an infinite loop (followed by dead 
code that can now be removed):


```c
for (;;) {
  // never exit loop
}
```

Because in math, positive numbers never +1 into negative numbers. 
And in C this is undefined behavior which is (modern 
understanding:) complete license for the compiler to do anything 
at all. And on the specific architecture we are specifically 
compiling for there is specific behavior--but who cares about 
that, this is optimization! And if you complained about it, well 
you were a sloppy coder actually, for wanting the target 
architecture's actual behavior with your actual code as you 
actually wrote it. (If you feel like defending C's honor here, 
please, I've heard it already. Everybody thinks very highly of 
the nasal demons joke.)


There are other cases where very security-minded software had 
defensive code that an optimizer decided would never be needed, 
that then exposed a software vulnerability, or there are 
'unnecessary' writes that are intended to remove a password from 
memory:


https://duckduckgo.com/?q=dead+code+elimination+security+vulnerability


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 12:53:14 UTC, Steven 
Schveighoffer wrote:
With the caveat, of course, that the recommendation to "leave a 
pointer on the stack" is not as easy to follow as one might 
think with the optimizer fighting against that. We need to add 
a better way to do that (similar to C# KeepAlive). I made an 
[attempt](https://code.dlang.org/packages/keepalive), but I 
think it's not guaranteed to work, I've already found ways to 
prove it fails.


For the moment I am personally quite happy
with any reasonable workaround
(use an object in the end of the main function,
put the reference to an object into some AA, whatever),
because now I firmly understand,
that the source of strange GC behavior
is DSE optimization (in this case).



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 13:05:07 UTC, Steven 
Schveighoffer wrote:
UB in C leaves traps for the programmer, similar to this trap 
you have found in the GC. Where code doesn't do what you are 
expecting it to do.


There is a difference, though.
As I've already said,
GC is a sort of 'environment',
the code of GC exits by it's own.

In C, no such code is 'inserted' by compiler
into code written by a programmer.

So, in C it is MY (potentially wrong) code.
In D, it is NOT MY code, it is GC.
From this point of view debugging
*may* be harder (especially by beginners, like me)



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Thursday, 23 September 2021 at 12:53:14 UTC, Steven 
Schveighoffer wrote:

Show me these rules!


They are here: 
https://dlang.org/spec/interfaceToC.html#storage_allocation


With the caveat, of course, that the recommendation to "leave a 
pointer on the stack" is not as easy to follow as one might 
think with the optimizer fighting against that.


Yes, as you explained me, the root of the
problem in my examples were dead store elimination.

We need to add a better way to do that (similar to C# 
KeepAlive).


Do you mean some function attribute?..



Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 8:10 AM, eugene wrote:
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven Schveighoffer 
wrote:

I find it interesting how you blame yourself for C's idiosyncrasies


Me? Blaming *myself* for C 'idiosyncrasies'? :) Where?


"When my C program crashes, I'm 100% sure I made something stupid"

One might argue that C's approach to memory management is a contributor 
to people writing code that fails.



I would say C has far more pitfalls than D.


No doubt - and I've never said C is "better" than D.
I was going to try betterC subset
(say, try to implement dynamic arrays),
but did not have much free time yet.


Your assertion that programming in GC languages may be harder than 
manual memory languages is what I was addressing.


My point is that C has a lot more memory management pitfalls than D, not 
addressing any "better than" arguments.





Check out the undefined behaviors for C.


Nothing interesting...
Most of UB in C are just programmer's sloppiness.
C requires a programmer to be careful/punctual,
much more careful, than ... a python, for ex.


UB in C leaves traps for the programmer, similar to this trap you have 
found in the GC. Where code doesn't do what you are expecting it to do.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/23/21 3:27 AM, eugene wrote:
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven Schveighoffer 
wrote:
Your experience is not typical though (clearly, as many of us 
long-time D users had no idea why it was happening).


Oh, yeah - I have special trait of bumping against
various low probability things :)

But for sure if this turns you off, I can understand how it can be too 
frustrating to learn the new rules.


Show me these rules!


They are here: https://dlang.org/spec/interfaceToC.html#storage_allocation

With the caveat, of course, that the recommendation to "leave a pointer 
on the stack" is not as easy to follow as one might think with the 
optimizer fighting against that. We need to add a better way to do that 
(similar to C# KeepAlive). I made an 
[attempt](https://code.dlang.org/packages/keepalive), but I think it's 
not guaranteed to work, I've already found ways to prove it fails.


-Steve


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven 
Schveighoffer wrote:
I find it interesting how you blame yourself for C's 
idiosyncrasies


Me? Blaming *myself* for C 'idiosyncrasies'? :) Where?


but not for D's ;)


I've been learning D for about 3 months only.


I would say C has far more pitfalls than D.


No doubt - and I've never said C is "better" than D.
I was going to try betterC subset
(say, try to implement dynamic arrays),
but did not have much free time yet.


Check out the undefined behaviors for C.


Nothing interesting...
Most of UB in C are just programmer's sloppiness.
C requires a programmer to be careful/punctual,
much more careful, than ... a python, for ex.




Re: Scope with owner types

2021-09-23 Thread Kagamin via Digitalmars-d-learn
Yes, the `return` attribute is what should do it. You also need 
to compile the code with -dip1000 option.


Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven 
Schveighoffer wrote:

But realize that C has it's share of "shocks" as well


Any language is just an instrument,
most of the 'shocks' come not from
languages themselves, but from the
'enviromment', so to say.

An example that came to mind...
Did you know that sending data via write()/send()
to a socket, that is in CLOSE_WAIT state,
results in sending data to nowhere and
write() indicates no error?

By the way, GC is a sort of 'environment' (not the language 
itself),

it acts behind the scenes (unless you are using it directly)

you are just more used to them (or maybe you have been lucky so 
far?)


Once I've been very 'lucky' with unaligned pointer dereference on 
ARM...




Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven 
Schveighoffer wrote:
In terms of any kind of memory management, whether it be ARC, 
manual, GC, or anything else, there will always be pitfalls. 
It's just that you have to get used to the pitfalls and how to 
avoid them.


100% agree.

I could see a person used to GC complaining that C requires you 
to free every pointer *exactly once*.


C (at compiler level) does not require this.
You can do it free()ly. ,)
With a subsequent... yes, 'shock' after you see 'double free or 
corruption' message.


Tell that imaginary person this: if (p) {free(p); p = NULL}, 
that's all.




Re: Program crash: GC destroys an object unexpectedly

2021-09-23 Thread eugene via Digitalmars-d-learn
On Wednesday, 22 September 2021 at 18:38:34 UTC, Steven 
Schveighoffer wrote:
Your experience is not typical though (clearly, as many of us 
long-time D users had no idea why it was happening).


Oh, yeah - I have special trait of bumping against
various low probability things :)

But for sure if this turns you off, I can understand how it can 
be too frustrating to learn the new rules.


Show me these rules!
Always use an object at the end of a function?
Make a second reference to an object somewhere on the heap?
The 'problem' here is that there is no clear rule.
Any reasonable 'hack' will do.