Re: How ptr arithmitic works??? It doesn't make any sense....
On Monday, 5 December 2022 at 18:01:47 UTC, ag0aep6g wrote: You can use bracket notation with pointers. You just need to move your closing parenthesis a bit. Assuming that `ptr` is a `void*`, these are all equivalent: ```d (cast(int*) ptr)[i] = whatever; *((cast(int*) ptr) + i) = whatever; *(cast(int*) (ptr + i * int.sizeof)) = whatever; ``` Oh, wow! That's sure interesting! Thanks a lot!
Re: Idiomatic D using GC as a library writer
On Monday, 5 December 2022 at 14:48:33 UTC, cc wrote: On Sunday, 4 December 2022 at 09:53:41 UTC, vushu wrote: [...] If your program runs, does some stuff, and terminates, use the GC. If your program runs, stays up for a while with user occasionally interacting with it, use the GC. If your program runs, and stays up 24/7 doing things in the background, use the GC. [...] Thanks a lot for your advice :)
Re: LSP-server for D?
On Monday, 5 December 2022 at 18:36:08 UTC, Per Nordlöw wrote: On Monday, 5 December 2022 at 12:38:07 UTC, Per Nordlöw wrote: On Monday, 5 December 2022 at 12:23:24 UTC, Per Nordlöw wrote: Is there a D lsp-server available? I couldn't find anything at https://code.dlang.org/search?q=lsp. Am I not using the correct search terms? Ahh, it's at https://code.dlang.org/packages/serve-d. Have anybody successfully used the LSP part of serve-d in conjunction with Emacs' lsp-mode as a frontend? Have you tried this? https://github.com/Pure-D/serve-d/blob/master/editor-emacs.md It should be similar for lsp-mode make sure you provide the proper parameters
Re: How ptr arithmitic works??? It doesn't make any sense....
On Monday, 5 December 2022 at 18:01:47 UTC, ag0aep6g wrote: You can use bracket notation with pointers. You just need to move your closing parenthesis a bit. Assuming that `ptr` is a `void*`, these are all equivalent... Yeah, there is such a thing! I'm sure you'll all like this example: ```d struct AAish(K, V, size_t s) { K key; V[s] value; // 5 + 1(\0) string toString() { import std.format : format; import core.stdc.string : strlen; auto result = value[0..strlen(value.ptr)]; return format("%s: %s", key, result); } } void stringCopy(C)(ref C src, string str) { import std.algorithm : min; auto len = min(src.length - 1, str.length); src[0 .. len] = str[0 .. len]; src[len] = '\0'; } enum n = 9; alias AA = AAish!(int, char, n); void main() { // First, we malloc for multiple AA() import core.stdc.stdlib; auto v = malloc(n * AA.sizeof); static assert( is (typeof(v) == void*) ); // Cast to use memory space for AA()'s auto ptr = cast(AA*)v; static assert( is (typeof(ptr) == AA*) ); // init AA()'s: foreach(i; 0..n) { ptr[i] = AA(i); } import std.stdio; ptr[0].value.stringCopy = "zero"; ptr[0].writeln; ptr[1].value.stringCopy = "one"; ptr[1].writeln; ptr[2].value.stringCopy = "two"; ptr[2].writeln; ptr[3].value.stringCopy = "three"; ptr[3].writeln; "...".writeln; //... ptr[8].value.stringCopy = "eight"; ptr[8].writeln; ptr[0..n/2].writeln; } /* Prints: 0: zero 1: one 2: two 3: three ... 8: eight [0: zero, 1: one, 2: two, 3: three] */ ``` SDB@79
Re: Thinking about the difference between fixed and 'dynamic' arrays.
On Sunday, 4 December 2022 at 09:54:53 UTC, Salih Dincer wrote: Recently DIP1044 was published about enum and although we can use `with()` instead we waste time unnecessarily... With cannot be used in calls. Hence when calling a function you need to either spell out the enum type or wrap the call in a with or multiple withs. I've never tried it, but the feature shown below is not available in D! Why not such good things? ```d enum Foo { a0 = 1, a1 } enum Bar: Foo { a2 // 3 } ``` Thanks... SDB@79 This is easy to add and costs almost no complexity
Re: LSP-server for D?
On Monday, 5 December 2022 at 12:38:07 UTC, Per Nordlöw wrote: On Monday, 5 December 2022 at 12:23:24 UTC, Per Nordlöw wrote: Is there a D lsp-server available? I couldn't find anything at https://code.dlang.org/search?q=lsp. Am I not using the correct search terms? Ahh, it's at https://code.dlang.org/packages/serve-d. Have anybody successfully used the LSP part of serve-d in conjunction with Emacs' lsp-mode as a frontend?
Re: How ptr arithmitic works??? It doesn't make any sense....
On Monday, 5 December 2022 at 15:08:41 UTC, rempas wrote: Got it! I guess they could also just allow us to use bracket notation to do the same thing. So something like: ```d foreach (i; 0 .. list.length) { (cast(int*)ptr[i]) = i; } ``` This is what happens with arrays anyways. And arrays ARE pointers to a contiguous memory block anyways so they could do the same with regular pointers. The example also looks more readable. You can use bracket notation with pointers. You just need to move your closing parenthesis a bit. Assuming that `ptr` is a `void*`, these are all equivalent: ```d (cast(int*) ptr)[i] = whatever; *((cast(int*) ptr) + i) = whatever; *(cast(int*) (ptr + i * int.sizeof)) = whatever; ```
Re: Idiomatic D using GC as a library writer
On Sunday, 4 December 2022 at 17:47:38 UTC, ryuukk_ wrote: On Sunday, 4 December 2022 at 09:53:41 UTC, vushu wrote: [...] D gives you the choice But the most important thing is your usecase, what kind of library are you making? Once you answer this question, you can then ask what your memory strategy should be, and then it is based on performance concerns D scale from microcontrollers to servers, drivers, games, desktop apps Your audience will determine what you should provide For a desktop app, a GC is an advantage For a driver or a game, it's not I agree with you i depends on the usecase, I will consider that thanks.
Re: Idiomatic D using GC as a library writer
On Monday, 5 December 2022 at 10:53:33 UTC, Guillaume Piolat wrote: On Sunday, 4 December 2022 at 21:55:52 UTC, Siarhei Siamashka wrote: Is it possible to filter packages in this list by @nogc or @safe compatibility? You can list DUB packages for "@nogc usage" https://code.dlang.org/?sort=score=20=library.nogc Cool, it looks like there is only a few nogc suitable libraries.
Re: Idiomatic D using GC as a library writer
On Monday, 5 December 2022 at 10:48:59 UTC, Guillaume Piolat wrote: There are legitimate uses cases when you can't afford the runtime machinery (attach/detach every incoming thread in a shared library), more than not being able to afford the GC from a performance point of view. [...] Thanks for the description of your usecase, good to know your perspective when considering using a library :)
Re: Idiomatic D using GC as a library writer
On Sunday, 4 December 2022 at 23:25:34 UTC, Adam D Ruppe wrote: On Sunday, 4 December 2022 at 22:46:52 UTC, Ali Çehreli wrote: That's way beyond my pay grade. Explain please. :) The reason that the GC stops threads right now is to ensure that something doesn't change in the middle of its analysis. [snip] That's a great explanation. Thanks.
Variation in prefix sum
I'm attempting to parallelize some program that solves recursive linear equations. Some of these, I believe, might be modified into prefix sums. Here are a handful of examples of the equations I'm dealing with. The conventional prefix sum is as follows: ``` y[i] = y[i-1] + x[i] ``` One equation that interests me is similar to prefix sum but with a multiplication: ``` y[i] = A*y[i-1] + x[i] ``` Another feature is deeper recursion: ``` y[i] = y[i-1] + y[i-2] + x[i] ``` Aside from these two versions, I'm wondering whether there are any resources that discuss how to convert situations like the one above into prefix sum form. Alternatively, ways for adopting/adapting prefix sum in order to make it more flexible. I read this [blog](https://www.scaler.com/topics/prefix-sum/), but I need more information about my situation.
Re: How ptr arithmitic works??? It doesn't make any sense....
On Monday, 5 December 2022 at 08:21:44 UTC, bauss wrote: Because it's much easier to work with. Ex. if you have an array of 4 signed 32 bit integers that you're pointing to then you can simply just increment the pointer by 1. If it was raw bytes then you'd have to increment the pointer by 4 to move to the next element. This is counter-intuitive if you're moving to the next element in a loop ex. This is how you'd do it idiomatically: ```d foreach (i; 0 .. list.length) { (*cast(int*)(ptr + i)) = i; } ``` Is this `(*cast(int*)(ptr + i)) = i;` or you did a mistake and wanted to write: `(*cast(int*)ptr + i) = i;`? Cause like we said before, the first operand must be a cast to the type for this to work right. Compared to: ```d foreach (i; 0 .. list.length) { (*cast(int*)(ptr + (i * 4))) = i; } ``` Got it! I guess they could also just allow us to use bracket notation to do the same thing. So something like: ```d foreach (i; 0 .. list.length) { (cast(int*)ptr[i]) = i; } ``` This is what happens with arrays anyways. And arrays ARE pointers to a contiguous memory block anyways so they could do the same with regular pointers. The example also looks more readable.
Re: Idiomatic D using GC as a library writer
On Sunday, 4 December 2022 at 09:53:41 UTC, vushu wrote: What are your thoughts about using GC as a library writer? If your program runs, does some stuff, and terminates, use the GC. If your program runs, stays up for a while with user occasionally interacting with it, use the GC. If your program runs, and stays up 24/7 doing things in the background, use the GC. If your program is a game meant to run at 60+fps, and any sudden skip or interrupt is unacceptable, no matter how minor (which it should be), plan carefully about how to manage your game objects, because naive GC instantiation and discarding isn't going to cut it. malloc/free, pre-allocated lists, and other strategies come into play here. In a desperate pinch you can also manually `GC.free` your GC-allocated objects but this is not recommended. The GC can still be used for allocations that are not likely to significantly affect performance every frame (strings, occasional user-generated information requests, first-load data instantiation, Steam avatars, etc) -- but also be even more careful when you start mixing and matching. I find that @nogc is a bit of a false idol though, even in situations where the GC is deliberately being avoided. It simply adds too much pain to trying to make everything compliant, and certain things just plain don't work (amazingly, the non-allocating form of toString can't be @nogc), so I simply avoid it and "be careful" (and/or hook into the GC so I can monitor if an unexpected allocation happens). If you're writing code that's going to run on a space shuttle or life support system, then yeah you might consider the extra effort, but in my use cases it simply fails the cost-benefit analysis. For any strategy, it's still a good idea to have a good understanding of or profile your allocations/deallocations so you're not just spending memory haphazardly or generating excessive collections.
Re: How ptr arithmitic works??? It doesn't make any sense....
On Sunday, 4 December 2022 at 19:00:15 UTC, H. S. Teoh wrote: This is true only if you're talking about pointers in the sense of pointers in assembly language. Languages like C and D add another layer of abstraction over this. Another thing with pointers is that it doesn't have "types". This is where you went wrong. In assembly language, yes, a pointer value is just a number, and there's no type associated with it. However, experience has shown that manipulating pointers at this raw, untyped level is extremely error-prone. Therefore, in languages like C or D, a pointer *does* have a type. It's a way of preventing the programmer from making silly mistakes, by associating a type (at compile-time only, of course) to the pointer value. It's a way of keeping track that address 1234 points to a short, and not to a float, for example. At the assembly level, of course, this type information is erased, and the pointers are just integer addresses. However, at compile-type, this type exists to prevent, or at least warn, the programmer from treating the value at the pointed-to address as the wrong type. This is not only because of data sizes, but the interpretation of data. A 32-bit value interpreted as an int is completely different from a 32-bit value interpreted as a float, for example. You wouldn't want to perform integer arithmetic on something that's supposed to be a float; the result would be garbage. In addition, although in theory memory is byte-addressable, many architectures impose alignment restrictions on values larger than a byte. For example, the CPU may require that 32-bit values (ints or floats) must be aligned to an address that's a multiple of 4 bytes. If you add 1 to an int* address and try to access the result, it may cause performance issues (the CPU may have to load 2 32-bit values and reassemble parts of them to form the misaligned 32-bit value) or a fault (the CPU may refuse to load a non-aligned address), which could be a silent failure or may cause your program to be forcefully terminated. Therefore, typed pointers like short* and int* may not be entirely an artifact that only exists in the compiler; it may not actually be legal to add a non-aligned value to an int*, depending on the hardware you're running on. Because of this, C and D implement pointer arithmetic in terms of the underlying value type. I.e., adding 1 to a char* will add 1 to the underlying address, but adding 1 to an int* will add int.sizeof to the underlying address instead of 1. I.e.: int[2] x; int* p = [0]; // let's say this is address 1234 p++;// p is now 1238, *not* 1235 (int.sizeof == 4) As a consequence, when you cast a raw pointer value to a typed pointer, you are responsible to respect any underlying alignment requirements that the machine may have. Casting a non-aligned address like 1235 to a possibly-aligned pointer like int* may cause problems if you're not careful. Also, the value type of the pointer *does* matter; you will get different results depending on the size of the type and any alignment requirements it may have. Pointer arithmetic involving T* operate in units of T.sizeof, *not* in terms of the raw pointer value. T Wow! Seriously, thanks a lot for this detailed explanation! I want to write a compiler and this type of explanations that not only give me the answer but explain me in detail why something happens are a gift for me! I wish I could meet you in person and buy you a coffee. Maybe one day, you never know! Thanks a lot and have an amazing day!
Re: LSP-server for D?
On Monday, 5 December 2022 at 12:23:24 UTC, Per Nordlöw wrote: Is there a D lsp-server available? I couldn't find anything at https://code.dlang.org/search?q=lsp. Am I not using the correct search terms? Ahh, it's at https://code.dlang.org/packages/serve-d.
LSP-server for D?
Is there a D lsp-server available? I couldn't find anything at https://code.dlang.org/search?q=lsp. Am I not using the correct search terms?
Re: Idiomatic D using GC as a library writer
On Sunday, 4 December 2022 at 21:55:52 UTC, Siarhei Siamashka wrote: Is it possible to filter packages in this list by @nogc or @safe compatibility? You can list DUB packages for "@nogc usage" https://code.dlang.org/?sort=score=20=library.nogc
Re: Idiomatic D using GC as a library writer
There are legitimate uses cases when you can't afford the runtime machinery (attach/detach every incoming thread in a shared library), more than not being able to afford the GC from a performance point of view. GC gives you higher productivity and better performance with the time gained. Now, @nogc code is good for performance since (even in a GC program) you will have no hidden allocation anymore, if you also disable postBlut and copy ctor, unlike in C++ where hidden copies are rempant. On Sunday, 4 December 2022 at 09:53:41 UTC, vushu wrote: What are your thoughts about using GC as a library writer? I don't use it always, but wish I could do it. Meanwhile, I make plenty of nothrow @nogc code. On Sunday, 4 December 2022 at 09:53:41 UTC, vushu wrote: If you wan't to include a library into your project aren't you more inclined to use a library which is gc free? Yes I am, but my needs are very specific and only the "betterC" subset fits it, and it's certainly not the nominal case in D, nor should it be. Some of the D target have strict requirements, for example Hipreme engine use audio-formats (nothrow @nogc), but audio-formats uses exceptions internally, maybe that will be an issue, depending on the flavour of D runtime it uses.
Re: Idiomatic D using GC as a library writer
On Sunday, 4 December 2022 at 23:37:39 UTC, Ali Çehreli wrote: On 12/4/22 15:25, Adam D Ruppe wrote: > which would trigger the write barrier. The thread isn't > allowed to complete this operation until the GC is done. According to my limited understanding of write barriers, the thread moving to 800 could continue because order of memory operations may have been satisfied. What I don't see is, what would the GC thread be waiting for about the write to 800? I'm not a specialist but I have the impression that GC write barrier and CPU memory ordering write barriers are 2 different things that confusedly use the same term for 2 completely different concepts. Would the GC be leaving behind writes to every page it scans, which have barriers around so that the other thread can't continue? But then the GC's write would finish and the other thread's write would finish. Ok, here is the question: Is there a very long standing partial write that the GC can perform like: "I write to 0x42, but I will finish it 2 seconds later. So, all other writes should wait?" > The GC finishes its work and releases the barriers. So, it really is explicit acquisition and releasing of these barriers... I think this is provided by the CPU, not the OS. How many explicit write barriers are there? Ali
Re: How ptr arithmitic works??? It doesn't make any sense....
On Monday, 5 December 2022 at 06:12:44 UTC, rempas wrote: On Sunday, 4 December 2022 at 16:40:17 UTC, ag0aep6g wrote: Not quite. Adding 10 to a T* means adding 10 * T.sizeof. Oh! I thought it was addition. Is there a specific reasoning for that if you are aware of? Because it's much easier to work with. Ex. if you have an array of 4 signed 32 bit integers that you're pointing to then you can simply just increment the pointer by 1. If it was raw bytes then you'd have to increment the pointer by 4 to move to the next element. This is counter-intuitive if you're moving to the next element in a loop ex. This is how you'd do it idiomatically: ```d foreach (i; 0 .. list.length) { (*cast(int*)(ptr + i)) = i; } ``` Compared to: ```d foreach (i; 0 .. list.length) { (*cast(int*)(ptr + (i * 4))) = i; } ```