Re: Unintentional sharing?
On Thu, Jun 06, 2024 at 05:49:39PM +, Andy Valencia via Digitalmars-d-learn wrote: > I was using instance initialization which allocated a new object. My > intention was this initialization would happen per-instance, but all > instances appear to share the same sub-object? That is, f1.b and f2.b > appear to point to a single object? [...] Yes, if you want a per-instance object, you need to do it in this(), not in the initializer. --T
Re: Unintentional sharing?
On Thursday, 6 June 2024 at 17:49:39 UTC, Andy Valencia wrote: I was using instance initialization which allocated a new object. My intention was this initialization would happen per-instance, but all instances appear to share the same sub-object? That is, f1.b and f2.b appear to point to a single object? Obviously I moved the new into the initializer code, but I hadn't appreciated how initial instance values were calculated once. Interestingly, this makes it similar to how Python calculates default argument values for functions. class Bar { int z = 3; } class Foo { auto b = new Bar(); } void main() { import std.stdio : writeln; auto f1 = new Foo(), f2 = new Foo(); f1.b.z = 0; writeln(f2.b.z); } This is a long standing issue: https://issues.dlang.org/show_bug.cgi?id=2947 I think with the next edition we can disallow (tail) mutable initializers for fields (and TLS globals too).
Re: Unintentional sharing?
On Thursday, 6 June 2024 at 17:49:39 UTC, Andy Valencia wrote: I was using instance initialization which allocated a new object. My intention was this initialization would happen per-instance, but all instances appear to share the same sub-object? That is, f1.b and f2.b appear to point to a single object? Obviously I moved the new into the initializer code, but I hadn't appreciated how initial instance values were calculated once. Interestingly, this makes it similar to how Python calculates default argument values for functions. class Bar { int z = 3; } class Foo { auto b = new Bar(); } void main() { import std.stdio : writeln; auto f1 = new Foo(), f2 = new Foo(); f1.b.z = 0; writeln(f2.b.z); } What you are seeing here is indeed sharing reference. It happens because type initializer sets fields after memory allocation but before constructor call, and so since it is using value known at compile time all instances will have share same reference. https://dlang.org/spec/class.html#constructors
Unintentional sharing?
I was using instance initialization which allocated a new object. My intention was this initialization would happen per-instance, but all instances appear to share the same sub-object? That is, f1.b and f2.b appear to point to a single object? Obviously I moved the new into the initializer code, but I hadn't appreciated how initial instance values were calculated once. Interestingly, this makes it similar to how Python calculates default argument values for functions. class Bar { int z = 3; } class Foo { auto b = new Bar(); } void main() { import std.stdio : writeln; auto f1 = new Foo(), f2 = new Foo(); f1.b.z = 0; writeln(f2.b.z); }
Re: How to pass in reference a fixed array in parameter
On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: I am currently trying to learn how to program in D. I thought that I could start by trying some maze generation algorithms. I have a maze stored as 2D array of structure defined as follow which keep tracks of wall positions: ~~~ struct s_cell { bool north = true; bool east = true; bool south = true; bool west = true; } ~~~ I try to create a 2D array of fixed length and pass it in parameter as a reference. Normally, in C, I would have used a pointer as parameter, and pass the address of the array. Here, I thought it would have been easier just to pass a slice of the array, since a slice is a reference to the original array. So I wrote the signature like this: ~~~ void main() { writeln("Maze generation demo"); s_cell [5][5] maze; print_maze (maze); } void print_maze ( s_cell [][] maze ) { } ~~~ My idea is that print_maze use a slice of what ever is sent in parameter. Unfortunately, I get the following error message: ~~~ Error: function `mprmaze.print_maze(s_cell[][] maze)` is not callable using argument types `(s_cell[5][5])` cannot pass argument `maze` of type `s_cell[5][5]` to parameter `s_cell[][] maze` ~~~ I tried to find a solution on the internet, but could not find anything, I stumble a lot on threads about Go or Rust language even if I specify "d language" in my search. Else is there other ways to pass an array as reference using parameter modifiers like: ref,in,out ... Else, can it be done the C way using pointers? Thank you. First things first, put `@safe:` on the top of the file or put `@safe` at the end of every function declarator. It makes anything that could be undefined behavior an error: ```d void main() @safe { writeln("Maze generation demo"); s_cell [5][5] maze; print_maze (maze); } // change to: ( const ref s_cell [5][5] maze ) void print_maze ( s_cell [][] maze ) @safe { } ``` A `T[]` is a pointer–length pair, aka. a slice. A `T[n]` is a block of `n` values of type `T`. Assuming you know a thing or two about C, a `T[n]` converts to a `T[]` like an `int` converts to a `long`: It’s lossless and safe, but not pointer compatible. For the same reason an `int*` can’t convert to a `long*`, a `T[m][n]` can’t convert to a `T[][]`. Also, if you’re new, be aware some people call slices “dynamic arrays,” which is really misleading sometimes. * If a function writes a maze, pass the maze by `ref`. Note that `ref` is not part of the parameter’s type (as in C++), but a property of the parameter akin to its type. * If a function only reads a maze, pass the maze by `const ref`; or `in` using the command-line option `-preview=in` which: allows rvalues and doesn’t bind by reference if the object bound is small and trivial to copy.
Re: bool passed by ref, safe or not ?
On Wednesday, 5 June 2024 at 18:31:12 UTC, Basile B. wrote: On Wednesday, 5 June 2024 at 01:18:06 UTC, Paul Backus wrote: On Tuesday, 4 June 2024 at 16:58:50 UTC, Basile B. wrote: ```d void main(string[] args) { ushort a = 0b; bool* b = cast(bool*) setIt(*b); assert(a == 0b); // what actually happens assert(a == 0b1110); // what would be safe } ``` [...] Do I corrupt memory here or not ? Is that a safety violation ? `cast(bool*)` is a safety violation. The only [safe values][1] for a `bool` are 0 (false) and 1 (true). By creating a `bool*` that points to a different value, you have violated the language's safety invariants. Because of this, operations that would normally be safe (reading or writing through the `bool*`) may now result in undefined behavior. [1]: https://dlang.org/spec/function.html#safe-values Obviously the topic was created because of the recent move D made. Sorry for the "catchy" aspect BTW. Now I remember that D safety is unrelated to undefined behaviors. I don’t think there’s any meaningful difference. If a program has UB, it can do anything, including corrupt memory. If a program corrupts memory, that’s UB. `@safe` means UB-free, which includes free of memory corruption.
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 10:36:50 UTC, Nick Treleaven wrote: ```d import std.stdio; alias s_cell = int; void main() { writeln("Maze generation demo"); s_cell [5][5] maze; int n; foreach (i, row; maze) foreach (j, col; row) maze[i][j] = n++; s_cell[][5] slices; foreach (i, _; maze) slices[i] = maze[i]; print_maze (slices); } void print_maze ( s_cell [][] maze ) { foreach (a; maze) a.writeln(); } ``` Thanks for the feedback Almost all my projects works intensively with multiple dimensions arrays. So I want to know the best way to manage multi dimensional arrays. I guess the best solution so far are: 1) Only use dynamic arrays. 2) Use a single dimension array, and compute the index value from x,y,z coordinates (Makes dynamic allocation easier). This solution could work well with pointers too. 3) Make my own data structure or class containing the array. Allowing to pass the structure/class by reference. Could allow encapsulating single or multi dimensional arrays. About .ptr, the documentation page state that: ~~~ The .ptr property for static and dynamic arrays will give the address of the first element in the array: ~~~ So I assumed that the following expressions where equivalent, but I guess the multiple dimensions do complicate things: ~~~ array.ptr == == [0] ~~~ So ommitting the "ref" keyword it's like if the data was read only even if the variable is not passed by value. That means that this signature cannot modify the content of the 2D array: ~~~ void print_maze ( s_cell [][] maze ) ~~~ For the create_maze() function, I would need to use the follwing signature since it changes the content of the array. ~~~ void print_maze ( ref s_cell [][] maze ) ~~~ I imagine `a.writeln();` is the same as `writeln(a);` ? Your foreach loops look better than mine. Here is the code I have been using to print the maze. ~~~ void print_maze ( s_cell [][] maze ) { //print top row, assume full foreach ( cell; maze[0] ) write("+---"); writeln("+"); for ( int y = 0; y < maze.length; y++) { //print content write("|"); //assume edge is always full for ( int x = 0; x < maze[y].length; x++) { write(" "); write( maze[y][x].east ? "|": " "); } writeln(); foreach ( cell; maze[y] ) write( cell.south ? "+---" : " " ); writeln("+"); } } ~~~ your iteration version is more neat: ~~~ foreach (i, row; maze) foreach (j, col; row) maze[i][j] = n++; ~~~ I like that using 2 variables (i,row) or (j,col) allow to access the variable later as a element in a collection or as an index. It's more flexible. I'll guess I'll need to read more code to avoid programming too much old school (^_^).
Re: bool passed by ref, safe or not ?
On Wednesday, 5 June 2024 at 01:18:06 UTC, Paul Backus wrote: On Tuesday, 4 June 2024 at 16:58:50 UTC, Basile B. wrote: ```d void main(string[] args) { ushort a = 0b; bool* b = cast(bool*) setIt(*b); assert(a == 0b); // what actually happens assert(a == 0b1110); // what would be safe } ``` [...] Do I corrupt memory here or not ? Is that a safety violation ? `cast(bool*)` is a safety violation. The only [safe values][1] for a `bool` are 0 (false) and 1 (true). By creating a `bool*` that points to a different value, you have violated the language's safety invariants. Because of this, operations that would normally be safe (reading or writing through the `bool*`) may now result in undefined behavior. [1]: https://dlang.org/spec/function.html#safe-values Obviously the topic was created because of the recent move D made. Sorry for the "catchy" aspect BTW. Now I remember that D safety is unrelated to undefined behaviors.
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 06:22:34 UTC, Eric P626 wrote: I tried the following signatures with the ref keyword and it did not change anything: ~~~ void print_maze ( ref s_cell maze ) void print_maze ( ref s_cell [][] maze ) ~~~ From what I found, arrays passed in parameters are always passed by reference. So the ref keyword seems pointless. There is one useful functionality about the ref keyword when passing arrays, it is that you can change the original array reference to another array reference. Ex. ``` void foo(ref int[] x) { x = [1,2,3]; } void bar(int[] y) { y = [1,2,3]; } void main() { auto x = [0,0,0]; auto y = [1,1,1]; foo(x); bar(y); writeln(x); writeln(y); } ``` The output of the program is: ``` [1, 2, 3] [1, 1, 1] ``` Of course in your case this doesn't matter, but just wanted to point out that adding ref to array parameters actually pose a function.
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 11:27:32 UTC, Nick Treleaven wrote: On Wednesday, 5 June 2024 at 09:24:23 UTC, evilrat wrote: for simple cases like this it might work, but 2d array is not even contiguous, A 2D static array is contiguous: https://dlang.org/spec/arrays.html#rectangular-arrays D static arrays, while using the same syntax, are implemented as a fixed rectangular layout in a contiguous block of memory Yeah ok, i might have messed up with columns last time, but it works. ```d int[5][5] test; foreach(i; 0..5) { foreach(j; 0..5) { test[i][j] = i * 5 + j; } } foreach(i; 0..25) { assert(test[0].ptr[i] == i); } ```
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 09:24:23 UTC, evilrat wrote: for simple cases like this it might work, but 2d array is not even contiguous, A 2D static array is contiguous: https://dlang.org/spec/arrays.html#rectangular-arrays D static arrays, while using the same syntax, are implemented as a fixed rectangular layout in a contiguous block of memory
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 10:27:47 UTC, Nick Treleaven wrote: foreach (i, row; maze) slices[i] = row; Sorry that assignment was wrong (edited at last minute). Fixed: ```d import std.stdio; alias s_cell = int; void main() { writeln("Maze generation demo"); s_cell [5][5] maze; int n; foreach (i, row; maze) foreach (j, col; row) maze[i][j] = n++; s_cell[][5] slices; foreach (i, _; maze) slices[i] = maze[i]; print_maze (slices); } void print_maze ( s_cell [][] maze ) { foreach (a; maze) a.writeln(); } ```
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 10:27:47 UTC, Nick Treleaven wrote: //~ void print_maze ( s_cell [][] maze... ) I meant to delete that line!
Re: How to pass in reference a fixed array in parameter
On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: ~~~ void main() { writeln("Maze generation demo"); s_cell [5][5] maze; print_maze (maze); } void print_maze ( s_cell [][] maze ) { } ~~~ This is how to do it without GC allocations (I have used `int` instead for demo purposes): ```d import std.stdio; alias s_cell = int; void main() { writeln("Maze generation demo"); s_cell [5][5] maze = [0, 1, 2, 3, 4]; s_cell[][5] slices; // static array of 5 slices foreach (i, row; maze) slices[i] = row; print_maze (slices); } //~ void print_maze ( s_cell [][] maze... ) void print_maze ( s_cell [][] maze ) { foreach (a; maze) a.writeln(); } ```
Re: How to pass in reference a fixed array in parameter
With accessor: ``` void main() { s_cell[] maze=make(5,5); s_cell a=maze.get(1,2); print_maze(maze); } void print_maze(s_cell[] maze) { } s_cell[] make(int width, int height) { return new s_cell[width*height]; } s_cell get(s_cell[] maze, int x, int y) { return maze[5*y+x]; //oops } ``` looks like you need to store the maze width somewhere.
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 06:22:34 UTC, Eric P626 wrote: Now according to the book, it's possible to assign a slice from a fixed array. This code will compile: ~~~ int[12] monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; int[] a_slice = monthDays; ~~~ The element types are both int, so the compiler can slice the static array. As if you had written `a_slice = monthDays[];`. How come the assignment does not work when passing a parameter. I tried the following and it failed: ~~~ s_cell [5][5] maze; The element type is s_cell[5]. s_cell [][] sliced_maze = maze; The element type of sliced_maze is s_cell[], so the element types are incompatible. ~~~ void print_maze ( ref s_cell maze ) void print_maze ( ref s_cell [][] maze ) ~~~ From what I found, arrays passed in parameters are always passed by reference. So the ref keyword seems pointless. You don't need `ref` to be able to read the array length and elements. However, if you want to modify the array length, and have it affect the caller's dynamic array, you need `ref`. --- The only solution left is to use pointers. But even this does not seems to work as in C. I created a function with different pointer signature and they all fails. Normally in C, this would have worked: ~~~ s_cell [5][5] maze; create_maze(); Pass `[0][0]` instead. ~~~ Error: function `mprmaze.create_maze(s_cell[][]* maze)` is not callable using argument types `(s_cell[5][5]*)` cannot pass argument `& maze` of type `s_cell[5][5]*` to parameter `s_cell[][]* maze` ~~~ s_cell[5][5] cannot implicitly convert to s_cell[][]. Now I think it expect a 2D array of pointers instead of a pointer on a 2D array. It's also not clear if there is a difference between those 2 notations: ~~~ maze.ptr ~~~ is a pointer to s_cell[5][5]. maze.ptr is a pointer to s_cell[5]. `.ptr` means a pointer to the first element of the array.
Re: How to pass in reference a fixed array in parameter
On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: I try to create a 2D array of fixed length and pass it in parameter as a reference. Normally, in C, I would have used a pointer as parameter, and pass the address of the array. Not obvious what you're trying to do. How would you do it in C? Use one dimensional array? You can use one dimensional array in D too. If dimensions of the maze are dynamic, you just write the maze creation function that allocates the maze as you want. In simple case: ``` void main() { writeln("Maze generation demo"); s_cell [5][5] maze; print_maze (maze); } void print_maze (ref s_cell [5][5] maze ) { } ``` With factory: ``` void main() { s_cell[][] maze=make(5,5); print_maze(maze); } void print_maze(s_cell[][] maze) { } s_cell[][] make(int width, int height) { } ```
Re: How to pass in reference a fixed array in parameter
On Wednesday, 5 June 2024 at 06:22:34 UTC, Eric P626 wrote: On Tuesday, 4 June 2024 at 16:19:39 UTC, Andy Valencia wrote: On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: Thanks for the comments. So far, I only managed to make it work by creating a dynamic array and keeping the same signature: ~~~ void main() { s_cell [][] maze = new s_cell[][](5,5); print_maze (maze); } void print_maze ( s_cell [][] maze ) { } ~~~ Now according to the book, it's possible to assign a slice from a fixed array. This code will compile: ~~~ int[12] monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; int[] a_slice = monthDays; ~~~ for simple cases like this it might work, but 2d array is not even contiguous, simpler case like s_cell[5][] might work too. How come the assignment does not work when passing a parameter. I tried the following and it failed: ~~~ s_cell [5][5] maze; s_cell [][] sliced_maze = maze; ~~~ with this message: ~~~ Error: cannot implicitly convert expression `maze` of type `s_cell[5][5]` to `s_cell[][]` ~~~ Is it because it's a 2D array (slice of slice)? I need to manually copy each slice manually, or use a utility function to do the copy? This is why it cannot auto-magically do it with just when passing a parameter. very likely this is the only solution - make a dynamic array by copying all elements. there was few old bug tracker issues discussed wrt to static arrays and join function but there is seems to be no agreement so far. ~~~ Error: function `mprmaze.create_maze(s_cell[][]* maze)` is not callable using argument types `(s_cell[5][5]*)` cannot pass argument `& maze` of type `s_cell[5][5]*` to parameter `s_cell[][]* maze` ~~~ Now I think it expect a 2D array of pointers instead of a pointer on a 2D array. It's also not clear if there is a difference between those 2 notations: ~~~ maze.ptr ~~~ there is, array itself is a tuple of length and pointer, the .ptr notation is just the data location, this is what you usually pass to C functions and not itself. to sum up, i wasn't able to make fixed-size arrays to work with dynamic arrays without making a copy, and I don't think this will change in the future because of various reasons including type system limitations and binary object formats. so if you really absolutely need static arrays for example to avoid GC allocations in hot path than you need to make function that takes fixed size array. in addition to that spec (https://dlang.org/spec/arrays.html#static-arrays) says static arrays is passed by value, unlike dynamic arrays that even when passed as length-and-pointer tuple will allow writing back to original data.
Re: bool passed by ref, safe or not ?
On Wednesday, 5 June 2024 at 09:09:40 UTC, Kagamin wrote: On Wednesday, 5 June 2024 at 01:18:06 UTC, Paul Backus wrote: The only safe values for a `bool` are 0 (false) and 1 (true). AFAIK that was fixed and now full 8-bit range is safe. `cast(bool) someByte` is fine - that doesn't reinterpret the bit representation. The problem is certain values such as `0x2` for the byte representation can cause the boolean to be both true and false: https://issues.dlang.org/show_bug.cgi?id=20148#c3 Void initialization of bool and bool union fields are now deprecated in @safe functions as of 2.109. There is a remaining case of casting an array to bool[], which I am working on disallowing in @safe.
Re: bool passed by ref, safe or not ?
On Wednesday, 5 June 2024 at 01:18:06 UTC, Paul Backus wrote: The only safe values for a `bool` are 0 (false) and 1 (true). AFAIK that was fixed and now full 8-bit range is safe.
Re: bool passed by ref, safe or not ?
Basile B. kirjoitti 4.6.2024 klo 19.58: I understand that the notion of `bool` doesn't exist on X86, hence what will be used is rather an instruction that write on the lower 8 bits, but with a 7 bits corruption. Do I corrupt memory here or not ? Is that a safety violation ? Viewing a valid boolean as an integer is still valid. Bit pattern of `false` is 0b_, and bit pattern of `true` is `0b_0001`. And even if the boolean is invalid, viewing it as an integer is probably valid if it was assigned to as an integer and not as an invalid boolean. There's a related case though where the situation is unclear. How do `ubytes` other than 1 or 0, when viewed as bools? We probably can't say it's undefined behaviour, since it is allowed in `@safe`. How I would define it, is that it's unspecific behaviour. That is if you have ```D bool* unspecified = cast(bool*) new ubyte(0xff); ``` then ``` // same as void-initialising bool a = *unspecified; // also same as void-initialising ubyte b = *unspecified; // Reliably 0xff. It's using the memory slot as bool that makes it unspecified, but what's in the memory slot is not affected. ubyte c = * cast(ubyte*) unspecified; // Unspecified which happens. One and only one must happen though. if (*unspecified) fun() else gun(); // Should this be required to call the same function as above? I'm not sure. if (*unspecified) fun() else gun(); ```
Re: How to pass in reference a fixed array in parameter
On Tuesday, 4 June 2024 at 16:19:39 UTC, Andy Valencia wrote: On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: I tried to find a solution on the internet, but could not find anything, I stumble a lot on threads about Go or Rust language even if I specify "d language" in my search. Aside from the excellent answer already present, I wanted to mention that searching with "dlang" has helped target my searches. Welcome to D! (From another newbie.) Andy Thanks for the comments. So far, I only managed to make it work by creating a dynamic array and keeping the same signature: ~~~ void main() { s_cell [][] maze = new s_cell[][](5,5); print_maze (maze); } void print_maze ( s_cell [][] maze ) { } ~~~ Now according to the book, it's possible to assign a slice from a fixed array. This code will compile: ~~~ int[12] monthDays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; int[] a_slice = monthDays; ~~~ How come the assignment does not work when passing a parameter. I tried the following and it failed: ~~~ s_cell [5][5] maze; s_cell [][] sliced_maze = maze; ~~~ with this message: ~~~ Error: cannot implicitly convert expression `maze` of type `s_cell[5][5]` to `s_cell[][]` ~~~ Is it because it's a 2D array (slice of slice)? I need to manually copy each slice manually, or use a utility function to do the copy? This is why it cannot auto-magically do it with just when passing a parameter. I tried the following signatures with the ref keyword and it did not change anything: ~~~ void print_maze ( ref s_cell maze ) void print_maze ( ref s_cell [][] maze ) ~~~ From what I found, arrays passed in parameters are always passed by reference. So the ref keyword seems pointless. --- The only solution left is to use pointers. But even this does not seems to work as in C. I created a function with different pointer signature and they all fails. Normally in C, this would have worked: ~~~ s_cell [5][5] maze; create_maze(); void create_maze ( s_cell *maze) { } ~~~ I get the following error ~~~ Error: function `mprmaze.create_maze(s_cell* maze)` is not callable using argument types `(s_cell[5][5]*)` cannot pass argument `& maze` of type `s_cell[5][5]*` to parameter `s_cell* maze` ~~~ But I get the idea of ambiguity, is the pointer pointing on a single cell, or an array of cells, so there might need a way to specify that it's not just an elements. I tried this: ~~~ s_cell [5][5] maze; create_maze(); void create_maze ( s_cell [][]*maze) { } ~~~ and get this error ~~~ Error: function `mprmaze.create_maze(s_cell[][]* maze)` is not callable using argument types `(s_cell[5][5]*)` cannot pass argument `& maze` of type `s_cell[5][5]*` to parameter `s_cell[][]* maze` ~~~ Now I think it expect a 2D array of pointers instead of a pointer on a 2D array. It's also not clear if there is a difference between those 2 notations: ~~~ maze.ptr ~~~ Do you have a code sample on how to pass a 2D array by pointer? So far, the pointer solution seems like the only method that should be compatible with both fixed and dynamic arrays unless I am mistaken.
Re: bool passed by ref, safe or not ?
On Wednesday, 5 June 2024 at 05:15:42 UTC, Olivier Pisano wrote: This is technically not a memory corruption, because as bool.sizeof < int.sizeof, you just write the low order byte of an int you allocated on the stack. It was not an int, it was a ushort. Anyway, what I wrote still applies.
Re: bool passed by ref, safe or not ?
On Tuesday, 4 June 2024 at 16:58:50 UTC, Basile B. wrote: question in the header, code in the body, execute on a X86 or X86_64 CPU I understand that the notion of `bool` doesn't exist on X86, hence what will be used is rather an instruction that write on the lower 8 bits, but with a 7 bits corruption. Do I corrupt memory here or not ? Is that a safety violation ? The problem is that while setIt() is @safe, your main function is not. So the pointer cast (which is not @safe) is permitted. A bool is a 1 byte type with two possible values : false (0) and true (1). When you set the value to false, you write 0 to the byte it points to. This is technically not a memory corruption, because as bool.sizeof < int.sizeof, you just write the low order byte of an int you allocated on the stack.
Re: bool passed by ref, safe or not ?
On Wednesday, 5 June 2024 at 01:18:06 UTC, Paul Backus wrote: On Tuesday, 4 June 2024 at 16:58:50 UTC, Basile B. wrote: you have violated the language's safety invariants. ah mais non.
Re: bool passed by ref, safe or not ?
On Tuesday, 4 June 2024 at 16:58:50 UTC, Basile B. wrote: ```d void main(string[] args) { ushort a = 0b; bool* b = cast(bool*) setIt(*b); assert(a == 0b); // what actually happens assert(a == 0b1110); // what would be safe } ``` [...] Do I corrupt memory here or not ? Is that a safety violation ? `cast(bool*)` is a safety violation. The only [safe values][1] for a `bool` are 0 (false) and 1 (true). By creating a `bool*` that points to a different value, you have violated the language's safety invariants. Because of this, operations that would normally be safe (reading or writing through the `bool*`) may now result in undefined behavior. [1]: https://dlang.org/spec/function.html#safe-values
Re: bool passed by ref, safe or not ?
On Tuesday, 4 June 2024 at 16:58:50 UTC, Basile B. wrote: question in the header, code in the body, execute on a X86 or X86_64 CPU ```d module test; void setIt(ref bool b) @safe { b = false; } void main(string[] args) { ushort a = 0b; bool* b = cast(bool*) setIt(*b); assert(a == 0b); // what actually happens assert(a == 0b1110); // what would be safe } ``` I understand that the notion of `bool` doesn't exist on X86, hence what will be used is rather an instruction that write on the lower 8 bits, but with a 7 bits corruption. Do I corrupt memory here or not ? I don't think so. You passed an address to a bool, which uses 8 bits of space, even though the compiler treats it as a 1-bit integer. In order for your code to do what you expect, all bool writes would have to be read/modify/write operations. I don't think anyone would prefer this. Is that a safety violation ? No, you are not writing to memory you don't have access to. An address is pointing at a byte level, not a bit level. -Steve
Re: bool passed by ref, safe or not ?
On Tuesday, 4 June 2024 at 16:58:50 UTC, Basile B. wrote: question in the header, code in the body, execute on a X86 or X86_64 CPU ```d module test; void setIt(ref bool b) @safe { b = false; } void main(string[] args) { ushort a = 0b; bool* b = cast(bool*) setIt(*b); assert(a == 0b); // what actually happens assert(a == 0b1110); // what would be safe } ``` I understand that the notion of `bool` doesn't exist on X86, hence what will be used is rather an instruction that write on the lower 8 bits, but with a 7 bits corruption. Do I corrupt memory here or not ? Is that a safety violation ? No everything is fine. The bool is the same size like byte or char. So your cast makes pointer to a byte. And this byte has to be made completely zero by setIt, otherwise it would not be false in the sense of bool type.
bool passed by ref, safe or not ?
question in the header, code in the body, execute on a X86 or X86_64 CPU ```d module test; void setIt(ref bool b) @safe { b = false; } void main(string[] args) { ushort a = 0b; bool* b = cast(bool*) setIt(*b); assert(a == 0b); // what actually happens assert(a == 0b1110); // what would be safe } ``` I understand that the notion of `bool` doesn't exist on X86, hence what will be used is rather an instruction that write on the lower 8 bits, but with a 7 bits corruption. Do I corrupt memory here or not ? Is that a safety violation ?
Re: How to pass in reference a fixed array in parameter
On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: I tried to find a solution on the internet, but could not find anything, I stumble a lot on threads about Go or Rust language even if I specify "d language" in my search. Aside from the excellent answer already present, I wanted to mention that searching with "dlang" has helped target my searches. Welcome to D! (From another newbie.) Andy
Re: How to pass in reference a fixed array in parameter
On Tuesday, 4 June 2024 at 12:22:23 UTC, Eric P626 wrote: I am currently trying to learn how to program in D. I thought that I could start by trying some maze generation algorithms. I have a maze stored as 2D array of structure defined as follow which keep tracks of wall positions: ~~~ struct s_cell { bool north = true; bool east = true; bool south = true; bool west = true; } ~~~ I try to create a 2D array of fixed length and pass it in parameter as a reference. Normally, in C, I would have used a pointer as parameter, and pass the address of the array. Here, I thought it would have been easier just to pass a slice of the array, since a slice is a reference to the original array. So I wrote the signature like this: ~~~ void main() { writeln("Maze generation demo"); s_cell [5][5] maze; print_maze (maze); } void print_maze ( s_cell [][] maze ) { } ~~~ My idea is that print_maze use a slice of what ever is sent in parameter. Unfortunately, I get the following error message: ~~~ Error: function `mprmaze.print_maze(s_cell[][] maze)` is not callable using argument types `(s_cell[5][5])` cannot pass argument `maze` of type `s_cell[5][5]` to parameter `s_cell[][] maze` ~~~ I tried to find a solution on the internet, but could not find anything, I stumble a lot on threads about Go or Rust language even if I specify "d language" in my search. You have declared static array here, they cannot be implicitly converted to dynamic arrays. It is not very obvious but it is a part of language design to avoid unnecessary GC allocations and for C compatibility reasons in some cases (e.g. strings known at compile implicitly has null appended to it to be able to pass pointer as is to C functions). IIRC you can explicitly cast it to s_cell[][] to make it work but it will allocate new array when you append to it. Else is there other ways to pass an array as reference using parameter modifiers like: ref,in,out ... `ref` is exactly for that. Else, can it be done the C way using pointers? absolutely, even ref behind the scenes will basically do the same thing anyway.
How to pass in reference a fixed array in parameter
I am currently trying to learn how to program in D. I thought that I could start by trying some maze generation algorithms. I have a maze stored as 2D array of structure defined as follow which keep tracks of wall positions: ~~~ struct s_cell { bool north = true; bool east = true; bool south = true; bool west = true; } ~~~ I try to create a 2D array of fixed length and pass it in parameter as a reference. Normally, in C, I would have used a pointer as parameter, and pass the address of the array. Here, I thought it would have been easier just to pass a slice of the array, since a slice is a reference to the original array. So I wrote the signature like this: ~~~ void main() { writeln("Maze generation demo"); s_cell [5][5] maze; print_maze (maze); } void print_maze ( s_cell [][] maze ) { } ~~~ My idea is that print_maze use a slice of what ever is sent in parameter. Unfortunately, I get the following error message: ~~~ Error: function `mprmaze.print_maze(s_cell[][] maze)` is not callable using argument types `(s_cell[5][5])` cannot pass argument `maze` of type `s_cell[5][5]` to parameter `s_cell[][] maze` ~~~ I tried to find a solution on the internet, but could not find anything, I stumble a lot on threads about Go or Rust language even if I specify "d language" in my search. Else is there other ways to pass an array as reference using parameter modifiers like: ref,in,out ... Else, can it be done the C way using pointers? Thank you.
Re: need help to use C++ callback from garnet
On Wednesday, 29 May 2024 at 09:01:13 UTC, evilrat wrote: On Wednesday, 29 May 2024 at 07:47:01 UTC, Dakota wrote: [...] (here is the signature of callback) https://github.com/microsoft/garnet/blob/ade2991f3737b9b5e3151d0dd0b614adfd4bcecd/libs/storage/Tsavorite/cc/src/device/async.h#L25 [...] Thanks for the tips.
Re: How does one attach a manifest file to a D executable on Windows?
On Sunday, 2 June 2024 at 21:46:41 UTC, solidstate1991 wrote: Well, it turns out I used the windres found in mingw instead of `rc.exe` since the latter cannot be found anywhere on my PC, even after reinstalling stuff. I need to hunt it down somehow. rc.exe comes with the Windows SDK - it gets installed in one of the subfolders of "C:\Program Files (x86)\Windows Kits\10\bin" (on my machine it's in "10.0.22000.0\x64").
Re: How does one attach a manifest file to a D executable on Windows?
On Sunday, 2 June 2024 at 19:11:10 UTC, solidstate1991 wrote: Added a few more line to my `resources.rc` file, it seems like the issue is the resource file not being touched at all. I've put `dflags "resources.res" platform="windows"` in my `dub.sdl` file, it doesn't even care if there's a typo in the resource file's path. Well, it turns out I used the windres found in mingw instead of `rc.exe` since the latter cannot be found anywhere on my PC, even after reinstalling stuff. I need to hunt it down somehow.
Re: How does one attach a manifest file to a D executable on Windows?
On Saturday, 25 May 2024 at 19:51:25 UTC, John Chapman wrote: Not tested but from memory I do this: 1) Copy that first XML snippet from the page you linked, save to a file called example.exe.manifest 2) Create a resource script file called resources.rc, with this at the top: 1 24 "example.exe.manifest" 3) Compile it with rc.exe 4) Include the resulting resources.res on your DMD command line You might also need to call InitCommonControls or InitCommonControlsEx before creating any windows. Added a few more line to my `resources.rc` file, it seems like the issue is the resource file not being touched at all. I've put `dflags "resources.res" platform="windows"` in my `dub.sdl` file, it doesn't even care if there's a typo in the resource file's path.
Re: Socket and spawn()
On Sunday, 2 June 2024 at 17:46:09 UTC, bauss wrote: If anything you should use a thread pool that each handles a set of sockets, instead of each thread being a single socket. Yup, thread pool it is. I'm still fleshing out the data structure which manages the incoming work presented to the pool, but here's what I have so far: https://sources.vsta.org:7100/dlang/file?name=tiny/rotor.d=tip Andy
Re: Socket and spawn()
On Friday, 31 May 2024 at 16:07:23 UTC, Andy Valencia wrote: I'm coding a server which takes TCP connections. I end up in the main thread with .accept() which hands me a Socket. I'd like to hand this off to a spawn()'ed thread to do the actual work. Aliases to mutable thread-local data not allowed. Is there some standard way to get something which _isn't_ in TLS? Or do I have to drop back to file descriptors and do my own socket handling? TIA, Andy I just want to point out that you should not spawn a thread for each accepted socket. That is very bad and expensive. You should instead make it non-blocking and use something like select to handle it. If anything you should use a thread pool that each handles a set of sockets, instead of each thread being a single socket.
Re: How does one attach a manifest file to a D executable on Windows?
On Saturday, 25 May 2024 at 19:51:25 UTC, John Chapman wrote: Not tested but from memory I do this: 1) Copy that first XML snippet from the page you linked, save to a file called example.exe.manifest 2) Create a resource script file called resources.rc, with this at the top: 1 24 "example.exe.manifest" 3) Compile it with rc.exe 4) Include the resulting resources.res on your DMD command line You might also need to call InitCommonControls or InitCommonControlsEx before creating any windows. Did just that too, didn't change anything.
Re: Socket and spawn()
On Friday, May 31, 2024 6:28:27 PM MDT Andy Valencia via Digitalmars-d-learn wrote: > On Friday, 31 May 2024 at 16:59:08 UTC, Jonathan M Davis wrote: > > Speaking as an old kernel engineer for the Sequent multiprocessor > product line, this is all very comfortable to me. I'm very glad > that D has a suitable selection of spinlocks, process semaphores, > and memory atomic operations. I can work with this! The way that D handles all of this is at its core the same as C/C++. The main difference is that the type system assumes that anything that isn't marked as shared or immutable is thread-local and can do optimizations based on that (though I'm not sure that that actually happens in practice right now). And in turn, you're supposed to get errors when you do stuff with a shared object which isn't guaranteed to be thread-safe (though not all of those checks are enabled by default at the moment). The result of this is supposed to be that the portions of your code which are operating on shared data are clearly segregated, whereas in C/C++, the type system doesn't give you any way of knowing what's actively being shared across threads. So, in principle, you're writing essentially what you want have written in C/C++, but the type system is helping you catch when you screw it up. The annoying part is that because the compiler can't know when it's actually thread-safe to access shared data (e.g. it has no clue when the programm associates a mutex with a set of data), you have to use explicit casts to thread-local to then be able to operate on the data when it is thread-safe (unless the type is designed to be used as shared, in which case, it's doing any necessary casting internally), whereas in C/C++, since the type system doesn't know or care about thread safety, it'll just let you access data whether it's properly protected or not. So, some folks get annoyed by the necessary casting, but in theory, it's the type system helping to minimize the risk of you shooting yourself in the foot. The idioms involved are basically the same as those used in C/C++ though, so anyone who understands those should be able to write thread-safe code in D fairly easily once they understand how shared works. > > In any case, you can freely cast between thread-local and > > shared. It's just that you need to be sure that when you do > > that, you're not violating the type system by having a > > thread-local reference to shared data access that shared data > > without first protecting it with a mutex. > > That was the trick for me; TLS implied to me that an > implementation would be free to arrange that the address of a > variable in one thread's TLS would not necessarily be accessible > from another thread. Now I'm clearer on the usage of the term > WRT the D runtime. All good. If you have a module-level or static variable that isn't shared or immutable, then each thread will get its own copy. So, those _might_ end up in TLS (I'm not sure if they are right now or not), but if you're just creating stuff on the fly, none of it is actually in TLS. And it's very common when dealing with shared or immutable data to create it first as thread-local and then cast it, since you know that it's not actually shared across threads at that point, and it's easier to construct that way. If we did want to start using TLS all over the place, then the casts would have to take that into account somehow, but I don't expect that that will happen. - Jonathan M Davis
Re: Socket and spawn()
On Friday, 31 May 2024 at 16:59:08 UTC, Jonathan M Davis wrote: Strictly speaking, unless you're dealing with a module or static-level variable, the object is not in TLS. It's treated as thread-local by the type system, and the type system will assume that no other thread has access to it, but you can freely cast it to shared or immutable and pass it across threads. It's just that it's up to you to make sure that you don't have a thread-local reference to shared data that isn't protected in a fashion that accessing the thread-local references is guarantee to be thread-safe (e.g. the appropriate mutex has been locked). Thank you; this is the most complete explanation I've found yet for hwo to look at data sharing in D. On the other hand, if you're actively sharing an object across threads, then you cast it to shared and give it to the other thread. But then you have to use an appropriate thread-synchronization mechanism (likely a mutex in the case of a socket) to ensure that accessing the object is thread-safe. Speaking as an old kernel engineer for the Sequent multiprocessor product line, this is all very comfortable to me. I'm very glad that D has a suitable selection of spinlocks, process semaphores, and memory atomic operations. I can work with this! In any case, you can freely cast between thread-local and shared. It's just that you need to be sure that when you do that, you're not violating the type system by having a thread-local reference to shared data access that shared data without first protecting it with a mutex. That was the trick for me; TLS implied to me that an implementation would be free to arrange that the address of a variable in one thread's TLS would not necessarily be accessible from another thread. Now I'm clearer on the usage of the term WRT the D runtime. All good. Thanks again, Andy
Re: Socket and spawn()
On Friday, 31 May 2024 at 19:48:37 UTC, kdevel wrote: Have you taken into consideration that each of the (pre-spawned) threads can call accept()? Your program may also accept in multiple processes on the same socket. [1] Yes, but I am planning on some global behavior--mostly concerning resource consumption--where that would make implementing the policy harder. I've indeed done the cast-to-shared and then cast-to-unshared and it's working fine. BTW, if the strategy forward is where the type system is going to assist with flagging code paths requiring allowance for multiple threads, it would be nice if the modifiers were available symmetrically. "shared" and "unshared", "mutable" and "immutable", and so forth? I'm using: alias Unshared(T) = T; alias Unshared(T: shared U, U) = U; and that's fine, but for core semantics of the language, it might make sense to treat these as first class citizens. Andy
Re: Socket and spawn()
On Friday, 31 May 2024 at 16:07:23 UTC, Andy Valencia wrote: I'm coding a server which takes TCP connections. I end up in the main thread with .accept() which hands me a Socket. I'd like to hand this off to a spawn()'ed thread to do the actual work. Have you taken into consideration that each of the (pre-spawned) threads can call accept()? Your program may also accept in multiple processes on the same socket. [1] [1] https://stackoverflow.com/questions/11488453/can-i-call-accept-for-one-socket-from-several-threads-simultaneously
Re: Socket and spawn()
On Friday, May 31, 2024 10:07:23 AM MDT Andy Valencia via Digitalmars-d-learn wrote: > I'm coding a server which takes TCP connections. I end up in the > main thread with .accept() which hands me a Socket. I'd like to > hand this off to a spawn()'ed thread to do the actual work. > > Aliases to mutable thread-local data not allowed. > > Is there some standard way to get something which _isn't_ in TLS? > Or do I have to drop back to file descriptors and do my own > socket handling? > > TIA, > Andy Strictly speaking, unless you're dealing with a module or static-level variable, the object is not in TLS. It's treated as thread-local by the type system, and the type system will assume that no other thread has access to it, but you can freely cast it to shared or immutable and pass it across threads. It's just that it's up to you to make sure that you don't have a thread-local reference to shared data that isn't protected in a fashion that accessing the thread-local references is guarantee to be thread-safe (e.g. the appropriate mutex has been locked). So, if you're just passing it to another thread, and that other thread is all that uses the object, then you would temporarily cast it to shared or immutable, give it to the other thread, and then that thread would cast it back to thread-local to use it, and the original thread would have nothing to do with it any longer. On the other hand, if you're actively sharing an object across threads, then you cast it to shared and give it to the other thread. But then you have to use an appropriate thread-synchronization mechanism (likely a mutex in the case of a socket) to ensure that accessing the object is thread-safe. So, typically, you would lock a mutex to ensure that no other thread is accessing the object, and then you temporarily cast away shared while the object is protected by the mutex so that you can do whatever you need to do with the object, and once you're ready to release the mutex, you make sure that no thread-local references to the object remain before releasing the mutex. So, any code actually operating on the object would do so while it's typed as thread-local, and the compiler would complain if you accidentally accessed it through the shared referenc to the data (though the compiler doesn't currently catch all such cases - the -preview=nosharedaccess switch turns on more of the checks, and that's supposed to be become the default eventually, but it hasn't yet). In any case, you can freely cast between thread-local and shared. It's just that you need to be sure that when you do that, you're not violating the type system by having a thread-local reference to shared data access that shared data without first protecting it with a mutex. And that typically means not having any thread-local references to the shared data except when the mutex is locked. But if all you're doing is passing an object across threads, then it's pretty straightforward, since you just cast it to shared or immutable to be able to pass it across threads and then cast back to thread-local on the other side to use it as normal again (you just need to make sure that you don't leave a reference to the data on the original thread when you do that). - Jonathan M Davis
Socket and spawn()
I'm coding a server which takes TCP connections. I end up in the main thread with .accept() which hands me a Socket. I'd like to hand this off to a spawn()'ed thread to do the actual work. Aliases to mutable thread-local data not allowed. Is there some standard way to get something which _isn't_ in TLS? Or do I have to drop back to file descriptors and do my own socket handling? TIA, Andy
Re: need help to use C++ callback from garnet
On Wednesday, 29 May 2024 at 07:47:01 UTC, Dakota wrote: I try use https://github.com/microsoft/garnet/blob/main/libs/storage/Tsavorite/cc/src/device/native_device_wrapper.cc from D Not sure how to make this work with D: ```c++ EXPORTED_SYMBOL FASTER::core::Status NativeDevice_ReadAsync(NativeDevice* device, uint64_t source, void* dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->ReadAsync(source, dest, length, callback, context); } EXPORTED_SYMBOL FASTER::core::Status NativeDevice_WriteAsync(NativeDevice* device, const void* source, uint64_t dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->WriteAsync(source, dest, length, callback, context); } ``` I need to define `FASTER::core::AsyncIOCallback callback` from D, any way to workaround ? (like modify garnet source code to support pass a C function callback) I am newbie to C++ and D, any help will be appreciate (here is the signature of callback) https://github.com/microsoft/garnet/blob/ade2991f3737b9b5e3151d0dd0b614adfd4bcecd/libs/storage/Tsavorite/cc/src/device/async.h#L25 ```cpp typedef void(*AsyncIOCallback)(IAsyncContext* context, Status result, size_t bytes_transferred); ``` This can be written as following to match namespace and mangling scheme, assuming IAsyncContext is opaque pointer here, though I don't remember if enum need namespace as well. But no guarantess anyways, try it and adapt it. Also I can't remember if string list makes proper namespace or you should put `FASTER.core` instead (without quotes). ```d enum Status : ubyte { Ok = 0, Pending = 1, NotFound = 2, OutOfMemory = 3, IOError = 4, Corruption = 5, Aborted = 6, } extern(C++, "FASTER", "core") class IAsyncContext; alias AsyncIOCallback = extern(C++, "FASTER", "core") void function(IAsyncContext context, Status result, size_t bytes_transferred); ```
need help to use C++ callback from garnet
I try use https://github.com/microsoft/garnet/blob/main/libs/storage/Tsavorite/cc/src/device/native_device_wrapper.cc from D Not sure how to make this work with D: ```c++ EXPORTED_SYMBOL FASTER::core::Status NativeDevice_ReadAsync(NativeDevice* device, uint64_t source, void* dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->ReadAsync(source, dest, length, callback, context); } EXPORTED_SYMBOL FASTER::core::Status NativeDevice_WriteAsync(NativeDevice* device, const void* source, uint64_t dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->WriteAsync(source, dest, length, callback, context); } ``` I need to define `FASTER::core::AsyncIOCallback callback` from D, any way to workaround ? (like modify garnet source code to support pass a C function callback) I am newbie to C++ and D, any help will be appreciate
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 23:18:46 UTC, Steven Schveighoffer wrote: On Tuesday, 28 May 2024 at 18:41:02 UTC, bauss wrote: On Tuesday, 28 May 2024 at 18:29:17 UTC, Ferhat Kurtulmuş wrote: On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); You can do `SysTime(unixTimeToStdTime(0))` to get a SysTime that is at the unix epoch. Also figured out the second question based on your result. Simply doing: ``` SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(milliseconds) ``` Seems to work. Note there is an `msecs` function: ```d SysTime(unixTimeToStdTime(0)) + milliseconds.msecs; ``` https://dlang.org/phobos/std_datetime_systime.html#unixTimeToStdTime https://dlang.org/phobos/core_time.html#msecs -Steve Thanks! That's a lot cleaner
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 18:41:02 UTC, bauss wrote: On Tuesday, 28 May 2024 at 18:29:17 UTC, Ferhat Kurtulmuş wrote: On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); You can do `SysTime(unixTimeToStdTime(0))` to get a SysTime that is at the unix epoch. Also figured out the second question based on your result. Simply doing: ``` SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(milliseconds) ``` Seems to work. Note there is an `msecs` function: ```d SysTime(unixTimeToStdTime(0)) + milliseconds.msecs; ``` https://dlang.org/phobos/std_datetime_systime.html#unixTimeToStdTime https://dlang.org/phobos/core_time.html#msecs -Steve
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 18:29:17 UTC, Ferhat Kurtulmuş wrote: On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); // Get the total milliseconds long milliseconds = unixTime.total!"msecs"; // Print the Unix time in milliseconds writeln("Unix time in milliseconds: ", milliseconds); } Thanks a lot. Also figured out the second question based on your result. Simply doing: ``` SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(milliseconds) ``` Seems to work.
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); // Get the total milliseconds long milliseconds = unixTime.total!"msecs"; // Print the Unix time in milliseconds writeln("Unix time in milliseconds: ", milliseconds); }
Get milliseconds from time and construct time based on milliseconds
I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks
Re: Hide console on Windows with app running SDL2
On Tuesday, 28 May 2024 at 12:45:39 UTC, Steven Schveighoffer wrote: On Tuesday, 28 May 2024 at 12:35:42 UTC, bauss wrote: Running into a couple of problems trying to hide the console that opens when running an app that uses sdl2. First of all I am trying to compile with this using dub: ``` "lflags": ["/SUBSYSTEM:windows"] ``` However that gives me the following error: ``` error LNK2019: unresolved external symbol WinMain ``` And then if I add a WinMain like below: ``` extern (Windows) int WinMain() { return 0; } ``` Then of course it doesn't work, but what is the obvious way to solve this? I basically just want to hide the console, but nothing seems to work straight out of the box. I think this is still relevant: https://wiki.dlang.org/D_for_Win32 -Steve Thanks a lot, that helped and solved the issue
Re: Hide console on Windows with app running SDL2
On Tuesday, 28 May 2024 at 12:35:42 UTC, bauss wrote: Running into a couple of problems trying to hide the console that opens when running an app that uses sdl2. First of all I am trying to compile with this using dub: ``` "lflags": ["/SUBSYSTEM:windows"] ``` However that gives me the following error: ``` error LNK2019: unresolved external symbol WinMain ``` And then if I add a WinMain like below: ``` extern (Windows) int WinMain() { return 0; } ``` Then of course it doesn't work, but what is the obvious way to solve this? I basically just want to hide the console, but nothing seems to work straight out of the box. I think this is still relevant: https://wiki.dlang.org/D_for_Win32 -Steve
Re: Implementation Details
On 28/05/2024 12:54 PM, Ruby The Roobster wrote: As of late, I have taken up an interest in learning about how the D language is implemented at a compiler level, specifically the GC implementation. Unfortunately, the source code is poorly documented, and is too large to simply read all of it in a reasonable amount of time. If anyone here can help me, or at least point me to relevant resources, I would be very grateful. From a theory standpoint this book should give you a pretty good overview of how GC's work. It is the book I recommend for introduction to GC's. https://www.amazon.com/Garbage-Collection-Handbook-International-Perspectives-dp-1032218037/dp/1032218037/ref=dp_ob_title_bk But yes that GC is very hard to get into, and its been tacked on over the years which make it even harder to untangle. Plus there is a memory allocator in there too.
Implementation Details
As of late, I have taken up an interest in learning about how the D language is implemented at a compiler level, specifically the GC implementation. Unfortunately, the source code is poorly documented, and is too large to simply read all of it in a reasonable amount of time. If anyone here can help me, or at least point me to relevant resources, I would be very grateful.
Re: Problem with clear on shared associative array?
On 28/05/2024 12:36 PM, Andy Valencia wrote: On Monday, 27 May 2024 at 04:04:03 UTC, mw wrote: Pls NOTE: it is a `sharded` (meaning trunk-ed) NON-concurrent map, not `shared` concurrent map. Assuming I put it in shared memory, in what way is it not able to be used concurrently? It seems to have the needed lock operations? Thanks, Andy A concurrent data structure handles all of this for you. AA's are not concurrent because it doesn't offer any protection. Protecting a data structure with a mutex doesn't make it concurrent, but it may allow you to use it concurrently safely. Subtle difference!
Re: Problem with clear on shared associative array?
On Monday, 27 May 2024 at 04:04:03 UTC, mw wrote: Pls NOTE: it is a `sharded` (meaning trunk-ed) NON-concurrent map, not `shared` concurrent map. Assuming I put it in shared memory, in what way is it not able to be used concurrently? It seems to have the needed lock operations? Thanks, Andy
Re: Problem with clear on shared associative array?
On Monday, 27 May 2024 at 00:43:47 UTC, Serg Gini wrote: On Sunday, 26 May 2024 at 20:15:54 UTC, Andy Valencia wrote: For others wrestling with this issue, I found out how to cast to unshared at this article: You can check also this solution https://github.com/DmitryOlshansky/sharded-map Pls NOTE: it is a `sharded` (meaning trunk-ed) NON-concurrent map, not `shared` concurrent map. These two words looks similar, but the meaning is very different.
Re: Problem with clear on shared associative array?
On Sunday, 26 May 2024 at 20:15:54 UTC, Andy Valencia wrote: For others wrestling with this issue, I found out how to cast to unshared at this article: You can check also this solution https://github.com/DmitryOlshansky/sharded-map
Re: Problem with clear on shared associative array?
On Sunday, 26 May 2024 at 20:00:50 UTC, Jonathan M Davis wrote: No operation on an associative array is thread-safe. As such, you should not be doing _any_ operation on a shared AA without first locking a mutex to protect it. Then you need to cast away shared to access or mutate it or do whatever it is you want to do with it other than pass it around. And then when you're done, you make sure that no thread-local references to the AA exist, and you release the mutex. ... Thank you, that's exactly the big picture explanation I was hoping for. For others wrestling with this issue, I found out how to cast to unshared at this article: https://forum.dlang.org/thread/jwasqvrvkpqzimlut...@forum.dlang.org Andy
Re: Problem with clear on shared associative array?
On Sunday, May 26, 2024 8:39:53 AM MDT Andy Valencia via Digitalmars-d-learn wrote: > The following code fails to compile; it appears from the error > message that the library's clear() function is not ready to act > on a shared AA? > > synchronized class F { > > private: > string[int] mydict; > > public: > void clear() { > this.mydict.clear(); > } > } > > void > main() > { > auto f = new shared F(); > f.clear(); > } No operation on an associative array is thread-safe. As such, you should not be doing _any_ operation on a shared AA without first locking a mutex to protect it. Then you need to cast away shared to access or mutate it or do whatever it is you want to do with it other than pass it around. And then when you're done, you make sure that no thread-local references to the AA exist, and you release the mutex. This is true for any type which is not specifically designed to be shared, and none of the built-in types are designed to be shared. They will work as shared so long as you protect them appropriately and then temporarily cast away shared to operate on them as thread-local, but they should never be mutated as shared, and it's on you to make sure that the object is actually protected appropriately when you cast away shared, since the language has no way of knowing when that's actually safe to do. It can just prevent you from accidentally accessing an object when it's shared, since when it's shared, the type system marks it as shared across threads and thus not thread-safe to access. The language is supposed to prevent you from doing any operations on a shared object which are not guaranteed to be thread-safe (which is pretty much anything other than passing it around by reference or pointer), but unfortunately, since that wasn't entirely implemented up front, some of those checks are currently behind the -preview=nosharedaccess flag and will be made the default at some point in the future (but not now). So, some shared operations may work when they really shouldn't, but the compiler will prevent you from calling a function like clear, because it operates on thread-local variables, not shared ones. And with regards to AAs, you will need to be particularly careful with the in operator, because it returns a pointer a value in the AA. So, if you cast away shared to operate on it and then use in, you'll get a thread-local pointer to the AA, meaning that the lock needs to stay in place as long as that pointer is around, whereas a function like clear is done as soon as its been called, so unless you're doing more with the AA at that point, you could release the lock then. Using synchronized is one way to get a mutex, and a synchronized function is implicitly shared, so your clear function is both synchronized and shared, meaning that you can call it on a shared object, and it will lock a mutex when it's called, but you still need to cast away shared from mydict to be able to call anything on it. The compiler is not smart enough to know that removing shared is thread-safe within your function, so it will not do it for you, and the clear function for AAs can't work on shared AAs, because it has no way of guaranteeing that that's thread-safe. So, the solution is that you must explicitly removed shared temporarily to call clear when you know that it's thread-safe to do so. - Jonathan M Davis
Problem with clear on shared associative array?
The following code fails to compile; it appears from the error message that the library's clear() function is not ready to act on a shared AA? synchronized class F { private: string[int] mydict; public: void clear() { this.mydict.clear(); } } void main() { auto f = new shared F(); f.clear(); }
Re: How does one attach a manifest file to a D executable on Windows?
On Saturday, 25 May 2024 at 13:13:08 UTC, solidstate1991 wrote: No, I meant something like this: https://learn.microsoft.com/en-us/windows/win32/controls/cookbook-overview Not tested but from memory I do this: 1) Copy that first XML snippet from the page you linked, save to a file called example.exe.manifest 2) Create a resource script file called resources.rc, with this at the top: 1 24 "example.exe.manifest" 3) Compile it with rc.exe 4) Include the resulting resources.res on your DMD command line You might also need to call InitCommonControls or InitCommonControlsEx before creating any windows.
Re: How does one attach a manifest file to a D executable on Windows?
On Friday, 24 May 2024 at 21:26:12 UTC, Ferhat Kurtulmuş wrote: I think this is what you need https://github.com/aferust/doitlater/tree/master/views/res No, I meant something like this: https://learn.microsoft.com/en-us/windows/win32/controls/cookbook-overview
Re: Parallel safe associative array?
https://code.dlang.org/packages/rust_interop_d wrapped: DashMap: is an implementation of a concurrent associative array/hashmap in Rust.
Re: How does one attach a manifest file to a D executable on Windows?
On Friday, 24 May 2024 at 21:04:53 UTC, Ferhat Kurtulmuş wrote: On Friday, 24 May 2024 at 19:07:24 UTC, solidstate1991 wrote: I have tried resource compiling, then using `dflags` in dug to add the resulting obj file, but I still get the issue of the old GUI style. I did that before, but I don't remember now. Probably you will figure that out based on this. https://gitlab.com/aferust/gtkdappcreator/-/tree/master/win_res?ref_type=heads I think this is what you need https://github.com/aferust/doitlater/tree/master/views/res
Re: How does one attach a manifest file to a D executable on Windows?
On Friday, 24 May 2024 at 19:07:24 UTC, solidstate1991 wrote: I have tried resource compiling, then using `dflags` in dug to add the resulting obj file, but I still get the issue of the old GUI style. I did that before, but I don't remember now. Probably you will figure that out based on this. https://gitlab.com/aferust/gtkdappcreator/-/tree/master/win_res?ref_type=heads
Parallel safe associative array?
I was playing with parallel programming, and experienced "undefined behavior" when storing into an Associative Array in parallel. Guarding the assignments with a synchronized barrier fixed it, of course. And obviously loading down your raw AA with thread barriers would be foolish. But this set me searching through the library for a standard Associative Array construct which _is_ thread safe? It didn't jump out at me. I know I can place such a thing within a synchronized class, but I was wondering if there's a standard AA which has the standard usage but is safe when called in parallel? Thanks, Andy
Re: Recommendations on porting Python to D
On Friday, 3 May 2024 at 17:53:41 UTC, mw wrote: On Friday, 3 May 2024 at 17:38:10 UTC, Chris Piker wrote: On Thursday, 25 April 2024 at 16:57:53 UTC, mw wrote: [...] Thanks for the suggestions. I put the question aside for a bit, but yesterday ran across a python transpiler here: https://github.com/py2many/py2many It already has support for C++, Go and others. Since I have mountains of python code created over many years, maybe it would be worth contributing to this project out of self interest. Can you take a look at py2many and see what you think about it? Getting D on the support list might be good. (Haven't checked its own implementation and output code quality.) But it says has output for Kotlin, Dart, these two languages are similar to D syntactically, so will be a good start. I took another quick look of the project, it uses the Python builtin `ast` module as parser, and visitor design pattern to implement the transcompiler, so I think it's of decent quality. HTH.
Re: Anybody know about SDL and particularly SDL_TTF initialization?
On Sunday, 12 May 2024 at 20:13:04 UTC, WhatMeWorry` wrote: INFO: SDL loaded v2.30.2 INFO: SDL initialized: 0 INFO: TTF loaded: v2.0.14 Error Program exited with code -1073741819 Something hit a null pointer, time to fire up the debugger :)
Re: Anybody know about SDL and particularly SDL_TTF initialization?
On Sunday, 12 May 2024 at 20:13:04 UTC, WhatMeWorry` wrote: This should be trivial, right? I've been looking at existing D repo code for hours. Can't figure why TTF_Init doesn't work? It would help if I could figure out how to use SDL_GetError() INFO: SDL loaded v2.30.2 INFO: SDL initialized: 0 INFO: TTF loaded: v2.0.14 Error Program exited with code -1073741819 loadSDL(); SDL_version v; SDL_GetVersion(); toStdout("SDL loaded v%d.%d.%d", v.major, v.minor, v.patch); auto initSDL = SDL_Init(SDL_INIT_EVERYTHING); // returns 0 on success toStdout("SDL initialized: %d", initSDL); auto loadTTF = loadSDLTTF(); SDL_TTF_VERSION(); toStdout("TTF loaded: v%d.%d.%d", v.major, v.minor, v.patch); auto initTTF = TTF_Init(); // SDL must be initialized before calls to this library No idea why this fails, seems alright to me. You can use: TTF_GetError() for a human-readable error message,when the call to TTF_Init() fails (return -1). Good luck Danny
Re: __gshared is "somewhat" transitive, isn't it ?
On Thursday, 16 May 2024 at 17:04:09 UTC, user1234 wrote: Given ```d struct S { int member; } __gshared S s; ``` It's clear that `s.member` is `__gshared` too, right ? What does happen for ```d struct S { int member; static int globalMember; } __gshared S s; ``` Is then `S.globalMember` a TLS variable ? (I'd expect that) `__gshared` is a storage class. It means, store this thing in the global memory segment. `static` storage class means store this thing in TLS. Storage classes are *not* transitive, and they are not type constructors. They optionally might apply a type constructor to the type (such as the `const` storage class), but not always. So in this case `typeof(s)` is `S`, not `__gshared S`. `s.member` is in the global segment since structs members are placed within the struct memory location (in this case, the global memory segment). `globalMember` is placed in TLS because it's storage class is `static`, and `static` means, do not store with the instance (which for `s` would mean the global memory segment), but rather in TLS. -Steve
Re: Setting field of struct object
On Monday, 22 January 2024 at 08:54:21 UTC, Danilo wrote: On Monday, 22 January 2024 at 08:35:01 UTC, Joel wrote: [...] Nonetheless, this usually used with Objects (new class/struct instances), like so: ```d import std; [...] Fluent Interface
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: On Sunday, 12 May 2024 at 22:03:21 UTC, Ferhat Kurtulmuş wrote: https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Ahh yes. Then use dlist Thank you. I read its source, and was curious so I wrote a small performance measurement: put 10,000 things in a FIFO, pull them back out, and loop around that 10,000 times. My FIFO resulted in: Also try the code I gave in this thread: https://forum.dlang.org/post/fgzvdhkdyevtzznya...@forum.dlang.org In fact, please use this facility in the standard library: https://dlang.org/phobos/std_datetime_stopwatch.html#benchmark SDB@79
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: On Sunday, 12 May 2024 at 22:03:21 UTC, Ferhat Kurtulmuş wrote: https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Ahh yes. Then use dlist Thank you. I read its source, and was curious so I wrote a small performance measurement: put 10,000 things in a FIFO, pull them back out, and loop around that 10,000 times. My FIFO resulted in: real0m1.589s user0m1.585s sys 0m0.004s And the dlist based one: real0m4.731s user0m5.211s sys 0m0.308s Representing the FIFO as a linked list clearly has its cost, but I found the increased system time interesting. OS memory allocations maybe? The code is spaghetti, fifo/dlist, but it seemed the easiest way to see the two API's being used side by side: version(fifo) { import tiny.fifo : FIFO; } else { import std.container.dlist : DList; } const uint ITERS = 10_000; const uint DEPTH = 10_000; void main() { version(fifo) { auto d = FIFO!uint(); } else { auto d = DList!uint(); } foreach(_; 0 .. ITERS) { foreach(x; 0 .. DEPTH) { version(fifo) { d.add(x); } else { d.insertBack(x); } } foreach(x; 0 .. DEPTH) { version(fifo) { assert(x == d.next()); } else { assert(x == d.front()); d.removeFront(); } } } } thank you for sharing the results. Everything I read about queues recommends doublylinked lists. With your array based implementatio if you are consuming the elements faster than pushing new elements, your array buffer never resize which is costly. This should explain why your array based queue is more performant.
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: Representing the FIFO as a linked list clearly has its cost, but I found the increased system time interesting. OS memory allocations maybe? I know you want FIFO, I usually keep this on hand for fixed size LIFO; It can easily convert to FIFO and doesn't use LinkedList: ```d class LIFO(T) { T * element; size_t length, size; this(size_t s) { element = cast(T*)new T[s]; length = s; } auto rewind() => size = length; bool empty() => !size; auto front() => element[size - 1]; auto popFront() => --size; auto pop() => empty ? T(0) : element[--size]; alias push = insertFront; auto insertFront(T value) in(size < length, "Stack is overflow!") => element[size++] = value; auto ref opDollar() => length; auto ref opIndex(size_t i) => element[i]; auto ref opSlice(size_t first, size_t last) => element[first..last]; } unittest { enum test = 7; auto stack = new LIFO!size_t(test); assert(!stack.size); foreach (prime; 1..test + 1) { stack.insertFront(prime); } assert(stack.size == test); // == 7 stack.writeln(": ", stack.length); // [7, 6, 5, 4, 3, 2, 1]: 7 stack[$/2].writeln("-", stack[0]); // 4-1 stack.rewind(); stack.size.write(": ["); // 10: while (auto next = stack.pop) { if (next == 1) next.writeln("]"); else next.write(", "); } stack.size.writeln; // 0 stack.rewind(); assert(stack.size == test); } SDB@79
Re: FIFO
On Sunday, 12 May 2024 at 22:03:21 UTC, Ferhat Kurtulmuş wrote: https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Ahh yes. Then use dlist Thank you. I read its source, and was curious so I wrote a small performance measurement: put 10,000 things in a FIFO, pull them back out, and loop around that 10,000 times. My FIFO resulted in: real0m1.589s user0m1.585s sys 0m0.004s And the dlist based one: real0m4.731s user0m5.211s sys 0m0.308s Representing the FIFO as a linked list clearly has its cost, but I found the increased system time interesting. OS memory allocations maybe? The code is spaghetti, fifo/dlist, but it seemed the easiest way to see the two API's being used side by side: version(fifo) { import tiny.fifo : FIFO; } else { import std.container.dlist : DList; } const uint ITERS = 10_000; const uint DEPTH = 10_000; void main() { version(fifo) { auto d = FIFO!uint(); } else { auto d = DList!uint(); } foreach(_; 0 .. ITERS) { foreach(x; 0 .. DEPTH) { version(fifo) { d.add(x); } else { d.insertBack(x); } } foreach(x; 0 .. DEPTH) { version(fifo) { assert(x == d.next()); } else { assert(x == d.front()); d.removeFront(); } } } }
Re: What prevents ImportC from using .h directly?
On Sunday, 12 May 2024 at 21:34:30 UTC, Chris Piker wrote: So, why does ImportC need *.c files exclusively? I'm sure it solves a problem, but I don't know what that problem is. Support for headers has been worked on, but had to be reverted: https://issues.dlang.org/show_bug.cgi?id=23479
Re: Find homography in D?
On Sunday, 21 April 2024 at 14:57:33 UTC, Paolo Invernizzi wrote: Hi, Someone can point me to a D implementation of the classical OpenCV find homography matrix? Thank you, Paolo Now, we can do image stitching using DCV. It needs improvements though. https://github.com/libmir/dcv/tree/master/examples/imagestitchinghomography
Re: FIFO
On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! [...] I don't know your use case, maybe you have a similar problem I had to solve years ago. https://forum.dlang.org/post/xktftztisodpngcow...@forum.dlang.org
Re: FIFO
On Sunday, 12 May 2024 at 21:08:24 UTC, Andy Valencia wrote: On Sunday, 12 May 2024 at 19:45:44 UTC, Ferhat Kurtulmuş wrote: On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. ... https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Andy Ahh yes. Then use dlist
What prevents ImportC from using .h directly?
Hi D Import D is working quite well so far. One limitation is that module definitions require a tiny *.c file which is often just: ```C #include ``` Creating this file is trivial and has almost no knock-on effects, except when dealing with single file programs. I have quite a few small utilities with dub headers. It would be handy if I could set an import path and use ImportC on the header file directly, skipping the small C file all together. A specific example in my case follows. Given a C-lib interface defined in the header file: ``` /usr/include/cspice/SpiceUsr.h ``` it would be neat if a dub header similar to the following worked: ```d #!/usr/bin/env dub /+ dub.sdl: name "some_app" cImportPaths "/usr/local/include/cspice" +/ import SpiceUsr; // ... source continues ``` So, why does ImportC need *.c files exclusively? I'm sure it solves a problem, but I don't know what that problem is.
Re: FIFO
On Sunday, 12 May 2024 at 19:45:44 UTC, Ferhat Kurtulmuş wrote: On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. ... https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Andy
Anybody know about SDL and particularly SDL_TTF initialization?
This should be trivial, right? I've been looking at existing D repo code for hours. Can't figure why TTF_Init doesn't work? It would help if I could figure out how to use SDL_GetError() INFO: SDL loaded v2.30.2 INFO: SDL initialized: 0 INFO: TTF loaded: v2.0.14 Error Program exited with code -1073741819 loadSDL(); SDL_version v; SDL_GetVersion(); toStdout("SDL loaded v%d.%d.%d", v.major, v.minor, v.patch); auto initSDL = SDL_Init(SDL_INIT_EVERYTHING); // returns 0 on success toStdout("SDL initialized: %d", initSDL); auto loadTTF = loadSDLTTF(); SDL_TTF_VERSION(); toStdout("TTF loaded: v%d.%d.%d", v.major, v.minor, v.patch); auto initTTF = TTF_Init(); // SDL must be initialized before calls to this library
Re: FIFO
On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! [...] "next" is not a usual range primitive word in dlang. Why not just using slist.
Re: FIFO
On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! [...] https://dlang.org/phobos/std_container_slist.html
Re: Deprecation: foreach: loop index implicitly converted from size_t to int
A horrible alternative would be to use `alias` on `size_t` to make up a new pseudo-type that is more aligned with the code logic. ``` alias integer = size_t; import std.stdio : writefln; void main() { auto arr = [ [5, 15], // 20 [2, 3, 2, 3], // 10 [3, 6, 2, 9], // 20 ]; foreach (integer i, row; arr) { double total = 0.0; foreach (e; row) total += e; auto avg = total / row.length; writefln("AVG [row=%d]: %.2f", i, avg); } } ```
FIFO
I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! /* * fifo.d * FIFO data structure */ module tiny.fifo; import std.exception : enforce; const uint GROWBY = 16; /* * This is a FIFO, with "hd" walking forward and "tl" trailing * behind: *tl hd /Add here next *v v * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 * * Mildly complicated by a module-size indexing. */ struct FIFO(T) { T[] items; ulong hd, tl, length; void add(T t) { // Make more room when needed if (this.items.length == this.length) { assert(this.hd == this.tl); // Add room and shuffle current contents auto olen = this.items.length; auto newlen = olen + GROWBY; this.items.length = newlen; this.tl = (this.tl + GROWBY) % newlen; // Shuffle what we're butted up against to their // new position at the top of this.items[] ulong moved = olen - this.hd; this.items[$ - moved .. $] = this.items[this.hd .. this.hd + moved]; } // Add item at next position this.items[hd] = t; this.hd = (this.hd + 1) % this.items.length; this.length += 1; } // Give back next T next() { enforce(this.length > 0, "next() from empty FIFO"); this.length -= 1; auto res = this.items[this.tl]; this.tl = (this.tl + 1) % this.items.length; return res; } } unittest { auto f = FIFO!uint(); f.add(1); f.add(2); f.add(3); assert(f.next() == 1); assert(f.next() == 2); assert(f.next() == 3); assert(f.length == 0); // Now overflow several times f = FIFO!uint(); foreach(x; 0 .. GROWBY * 3 + GROWBY/2) { f.add(x); } foreach(x; 0 .. GROWBY * 3 + GROWBY/2) { assert(f.next() == x); } assert(f.length == 0); } version(unittest) { void main() { } }
Re: How to load a DLL file in D?
On Saturday, 11 May 2024 at 20:04:38 UTC, Lance Bachmeier wrote: On Saturday, 11 May 2024 at 19:33:03 UTC, solidstate1991 wrote: I know that BindBC exists and otherwise would use it, but the bigger the library, the more extra hurdle it'll have. When I did a few bindings with it, I had to order the functions the right way, so I could do things much quicker with the Ctrl+Alt+Shift trick under VSCode, and even then having to write both a statically linked and dynamically linked version (the latter which required the functions to be loaded individually into function pointers). Maybe I should write some automation tool... You might find this package useful https://code.dlang.org/packages/dynamic Also relevant if they're C functions: https://forum.dlang.org/post/qxctappnigkwvaqak...@forum.dlang.org And this if you want to convert C headers to D code: https://forum.dlang.org/post/ugvc3o$5t3$1...@digitalmars.com
Re: How to load a DLL file in D?
On Saturday, 11 May 2024 at 19:33:03 UTC, solidstate1991 wrote: I know that BindBC exists and otherwise would use it, but the bigger the library, the more extra hurdle it'll have. When I did a few bindings with it, I had to order the functions the right way, so I could do things much quicker with the Ctrl+Alt+Shift trick under VSCode, and even then having to write both a statically linked and dynamically linked version (the latter which required the functions to be loaded individually into function pointers). Maybe I should write some automation tool... You might find this package useful https://code.dlang.org/packages/dynamic
Re: Why is Phobos `Flag` so overthought ?
On Thursday, 9 May 2024 at 18:48:12 UTC, Nick Treleaven wrote: We have a tool in our box already called `true` and that solves the problem. If we had to type out the full name of every argument passed to every function ever written we may as well just adopt ObjC Cocoa style and call it StopWatchWithAutoStartBool(). Strawman. Not at all. I mean exactly that. Why do you believe this function is so important it needs to have its argument type explicitly stated, when most functions don't? Either that, or you believe all functions should. It's arbitrary and pointless.
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 16:33:53 UTC, Nick Treleaven wrote: Arrays evaluate to true in boolean conditions if their `.ptr` field is non-null. This is bug-prone and I hope we can remove this in the next edition. ... A string literal's `.ptr` field is always non-null, because it is null-terminated. Thank you! Andy
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 15:23:39 UTC, Andy Valencia wrote: On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer wrote: Yes, we say that a type has "truthiness" if it can be used in a condition (`while`, `if`, `assert`, etc). So if I may ask for one more small clarification... WRT "truthiness", I've observed that empty arrays are treated as false, non-empty as true. Arrays evaluate to true in boolean conditions if their `.ptr` field is non-null. This is bug-prone and I hope we can remove this in the next edition. However, although I thought a string was basically an immutable array of characters, "" is treated as true, not false? A string literal's `.ptr` field is always non-null, because it is null-terminated.
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer wrote: Yes, we say that a type has "truthiness" if it can be used in a condition (`while`, `if`, `assert`, etc). So if I may ask for one more small clarification... WRT "truthiness", I've observed that empty arrays are treated as false, non-empty as true. However, although I thought a string was basically an immutable array of characters, "" is treated as true, not false? Thanks again, Andy
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
On Friday, 10 May 2024 at 13:27:40 UTC, Dukc wrote: Steven Schveighoffer kirjoitti 10.5.2024 klo 16.01: On Friday, 10 May 2024 at 11:05:28 UTC, Dukc wrote: This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! This would be weak pure since the reference is mutable. This cannot be memoized. The difference is the type. With a pointer parameter (both a bare one and one in a struct), the compiler can cache the result only when the pointed data is similar. However, here we have an integer parameter. It can be cached if it itself is similar to the one in the other function call. The compiler doesn't have to know, nor can know, when a `size_t` is a pointer in disguise. This why I would just use ref counting if I were the topic author, trying to be smart will often comes back when one doesn't expect. And as stated by previous author if the goal is to have self-clearable weak reference it will need some infrastructure anyway, so tbh this will greatly outweight any possible benefits of having weak refs.
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
Steven Schveighoffer kirjoitti 10.5.2024 klo 16.01: On Friday, 10 May 2024 at 11:05:28 UTC, Dukc wrote: This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! This would be weak pure since the reference is mutable. This cannot be memoized. The difference is the type. With a pointer parameter (both a bare one and one in a struct), the compiler can cache the result only when the pointed data is similar. However, here we have an integer parameter. It can be cached if it itself is similar to the one in the other function call. The compiler doesn't have to know, nor can know, when a `size_t` is a pointer in disguise.
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
On Friday, 10 May 2024 at 11:05:28 UTC, Dukc wrote: This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! This would be weak pure since the reference is mutable. This cannot be memoized. -Steve
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
evilrat kirjoitti 9.5.2024 klo 18.19: ```d struct WeakRef(T) { private size_t _handle; // same size as a pointer this(T* ptr) { _handle = cast(size_t) ptr; } T* getRef() { return cast(T*) _handle; } // do the rest ... } ``` [1] https://code.dlang.org/packages/automem There is a hidden danger with using this struct. Since `getRef` is a template, it will be inferred as `pure`. Now, consider a function using it: ```D auto derefer(WeakrefT)(WeakrefT wr) => *wr.getRef; ``` This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! You probably should add some never-executed dummy operation to `getRef` that prevents it from becoming `pure` if you go with this design.
Re: moving from classical lex/yacc to pegged parser
Dmitry Ponyatov kirjoitti 9.5.2024 klo 11.30: > And I also can't figure out how to inherit `ParseTree` with all my script language objects to get AST right from pegged parser. Should I use some superloop with lot of matches to process parsed `pt` tree into something I need myself, to drop all unneeded parsing meta info and get clean semantic AST? Pegged can help you with that filtering part, at least to some extent. Remember you can use : and ; prefix operators in the grammar spec, and Pegged will drop the needless nodes for you. Or do the reverse, use ^ prefix operator (or write a new rule) to make a node out of Pegged builtins.