Re: pointer to object resolution
On Friday, 11 May 2018 at 15:24:08 UTC, Steven Schveighoffer wrote: On 5/11/18 8:53 AM, Alex wrote: This behaves differently, w.r.t. to an arbitrary method, like "operator". Why? Is there any workaround? operators don't follow pointers. Imagine if you had a struct that overloads "+" and then you wanted to use pointer arithmetic, but instead it called ptr.opBinary. Ah! The workaround is to dereference the pointer. e.g. 42 in *sptr; -Steve Thanks a lot!
Re: getOpt with shared
On 5/11/18 2:49 PM, Jonathan M Davis wrote: On Friday, May 11, 2018 14:31:17 Steven Schveighoffer via Digitalmars-d- learn wrote: On 5/11/18 1:25 PM, Danny Arends wrote: Hey all, I have been working on creating a multi-threaded application, so I have a shared configuration object which hold several command line parameters (which I fill using getopt). The problem is that I get deprecation warnings when trying to set numerical values: /usr/include/dmd/phobos/std/getopt.d(895,36): Deprecation: read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(*receiver, 1) instead. using getopt with a shared object and boolean values seems completely broken: /usr/include/dmd/phobos/std/getopt.d(895,34): Error: operation not allowed on bool *receiver += 1 /usr/include/dmd/phobos/std/getopt.d(751,46): Error: template instance `std.getopt.handleOption!(shared(bool)*)` error instantiating /usr/include/dmd/phobos/std/getopt.d(435,15):6 recursive instantiations from here: getoptImpl!(string, shared(string)*, string, shared(string)*, string, shared(VSync)*, string, shared(ulong)*, string, shared(bool)*, string, shared(Verbose)*) Is getopt not supposed to be used with shared structs ? No, just fill in a local copy, and then copy it to the shared location. In the case where all you want is read-only access to the data, build it once and then cast to immutable: immutable Config config; void main(string[] args) { Config localConfig; getopt(...); // fill in localConfig // VERY IMPORTANT, only do this ONCE, and don't use it before this line *(cast()&config) = localConfig; } It should now be accessible from all threads. Normally, this is not encouraged (casting away immutable), but the compiler gets that an immutable global is allowed to be initialized once (in fact, you can do this without casting inside shared static constructors). Except that because this is done outside of a shared static constructor, you're technically mutating immutable data. This _should_ work, but it is violating the type system, and technically, the compiler is allowed to assume that config is Config.init everywhere. In practice, I wouldn't expect a problem, but because it's violating the type system, all bets are off. It's not a problem. The compiler cannot assume the value is .init because it doesn't have access to the whole codebase to see if some static ctor has changed it. Effectively, you ARE changing it in a static ctor, but just after all the other static ctors have run. Crucially noted as well: don't use this value inside a static ctor! -Steve
Re: getOpt with shared
On Friday, May 11, 2018 14:31:17 Steven Schveighoffer via Digitalmars-d- learn wrote: > On 5/11/18 1:25 PM, Danny Arends wrote: > > Hey all, > > > > I have been working on creating a multi-threaded application, so I have > > a shared configuration object which hold several command line parameters > > (which I fill using getopt). > > > > The problem is that I get deprecation warnings when trying to set > > numerical values: > > > > /usr/include/dmd/phobos/std/getopt.d(895,36): Deprecation: > > read-modify-write operations are not allowed for shared variables. Use > > core.atomic.atomicOp!"+="(*receiver, 1) instead. > > > > using getopt with a shared object and boolean values seems completely > > broken: > > > > /usr/include/dmd/phobos/std/getopt.d(895,34): Error: operation not > > allowed on bool *receiver += 1 > > /usr/include/dmd/phobos/std/getopt.d(751,46): Error: template instance > > `std.getopt.handleOption!(shared(bool)*)` error instantiating > > /usr/include/dmd/phobos/std/getopt.d(435,15):6 recursive > > instantiations from here: getoptImpl!(string, shared(string)*, string, > > shared(string)*, string, shared(VSync)*, string, shared(ulong)*, string, > > shared(bool)*, string, shared(Verbose)*) > > > > Is getopt not supposed to be used with shared structs ? > > No, just fill in a local copy, and then copy it to the shared location. > > In the case where all you want is read-only access to the data, build it > once and then cast to immutable: > > immutable Config config; > > void main(string[] args) > { > Config localConfig; > getopt(...); // fill in localConfig > // VERY IMPORTANT, only do this ONCE, and don't use it before this > line *(cast()&config) = localConfig; > } > > It should now be accessible from all threads. > > Normally, this is not encouraged (casting away immutable), but the > compiler gets that an immutable global is allowed to be initialized once > (in fact, you can do this without casting inside shared static > constructors). Except that because this is done outside of a shared static constructor, you're technically mutating immutable data. This _should_ work, but it is violating the type system, and technically, the compiler is allowed to assume that config is Config.init everywhere. In practice, I wouldn't expect a problem, but because it's violating the type system, all bets are off. - Jonathan M Davis
Re: getOpt with shared
On 5/11/18 1:25 PM, Danny Arends wrote: Hey all, I have been working on creating a multi-threaded application, so I have a shared configuration object which hold several command line parameters (which I fill using getopt). The problem is that I get deprecation warnings when trying to set numerical values: /usr/include/dmd/phobos/std/getopt.d(895,36): Deprecation: read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(*receiver, 1) instead. using getopt with a shared object and boolean values seems completely broken: /usr/include/dmd/phobos/std/getopt.d(895,34): Error: operation not allowed on bool *receiver += 1 /usr/include/dmd/phobos/std/getopt.d(751,46): Error: template instance `std.getopt.handleOption!(shared(bool)*)` error instantiating /usr/include/dmd/phobos/std/getopt.d(435,15): 6 recursive instantiations from here: getoptImpl!(string, shared(string)*, string, shared(string)*, string, shared(VSync)*, string, shared(ulong)*, string, shared(bool)*, string, shared(Verbose)*) Is getopt not supposed to be used with shared structs ? No, just fill in a local copy, and then copy it to the shared location. In the case where all you want is read-only access to the data, build it once and then cast to immutable: immutable Config config; void main(string[] args) { Config localConfig; getopt(...); // fill in localConfig // VERY IMPORTANT, only do this ONCE, and don't use it before this line *(cast()&config) = localConfig; } It should now be accessible from all threads. Normally, this is not encouraged (casting away immutable), but the compiler gets that an immutable global is allowed to be initialized once (in fact, you can do this without casting inside shared static constructors). -Steve
Re: getOpt with shared
On Friday, May 11, 2018 18:01:18 Danny Arends via Digitalmars-d-learn wrote: > On Friday, 11 May 2018 at 17:49:17 UTC, Jonathan M Davis wrote: > > On Friday, May 11, 2018 17:25:44 Danny Arends via > > > > Digitalmars-d-learn wrote: > >> [...] > > > > getopt is designed to be single-threaded. The keyword shared is > > not used a single type in that module. If you want to use > > shared with anything in D, you have three options: > > > > [...] > > Hey Jonathan, > > Thanks for the long and insightful answer. > The object is indeed constructed from the main thread, but > afterwards multiple threads need to read the values given via the > command line. since everything in the object is read only I was > hoping to get away with making it shared. > > I should just define tls variables to use with getopt and then > set the corresponding variables in the shared object. If you want to operate on that data as shared, then yes. But if you're really just looking for each thread to have its own copy, I'd suggest that you either give each thread its own copy on thread creation or pass it using std.concurrency rather than trying to deal with a shared variable - especially since the type system has no way to know that you're just planning to read from the shared variable after that, and it will scream at you for various operations - and once shared is fully locked down, it will probably scream if you do much of _anything_ with shared, since at that point, the compiler would only allow operations that were either marked with shared or where it could guarantee that they were thread-safe. - Jonathan M Davis
Re: getOpt with shared
On Friday, 11 May 2018 at 17:49:17 UTC, Jonathan M Davis wrote: On Friday, May 11, 2018 17:25:44 Danny Arends via Digitalmars-d-learn wrote: [...] getopt is designed to be single-threaded. The keyword shared is not used a single type in that module. If you want to use shared with anything in D, you have three options: [...] Hey Jonathan, Thanks for the long and insightful answer. The object is indeed constructed from the main thread, but afterwards multiple threads need to read the values given via the command line. since everything in the object is read only I was hoping to get away with making it shared. I should just define tls variables to use with getopt and then set the corresponding variables in the shared object. Danny
Re: getOpt with shared
On Friday, May 11, 2018 17:25:44 Danny Arends via Digitalmars-d-learn wrote: > Hey all, > > I have been working on creating a multi-threaded application, so > I have a shared configuration object which hold several command > line parameters (which I fill using getopt). > > The problem is that I get deprecation warnings when trying to set > numerical values: > > /usr/include/dmd/phobos/std/getopt.d(895,36): Deprecation: > read-modify-write operations are not allowed for shared > variables. Use core.atomic.atomicOp!"+="(*receiver, 1) instead. > > using getopt with a shared object and boolean values seems > completely broken: > > /usr/include/dmd/phobos/std/getopt.d(895,34): Error: operation > not allowed on bool *receiver += 1 > /usr/include/dmd/phobos/std/getopt.d(751,46): Error: template > instance `std.getopt.handleOption!(shared(bool)*)` error > instantiating > /usr/include/dmd/phobos/std/getopt.d(435,15):6 recursive > instantiations from here: getoptImpl!(string, shared(string)*, > string, shared(string)*, string, shared(VSync)*, string, > shared(ulong)*, string, shared(bool)*, string, shared(Verbose)*) > > Is getopt not supposed to be used with shared structs ? getopt is designed to be single-threaded. The keyword shared is not used a single type in that module. If you want to use shared with anything in D, you have three options: 1. Use core.atomic to atomically do stuff like increment a integer. 2. Use a mutex (or synchronized block) to protect access to a shared object. You lock the mutex before accessing the object (and before _all_ accesses to that object). Within that section of code, you cast away shared and operate on the object as thread-local. Then at the end of that section, before releasing the lock, you make sure that no thread-local references to the shared object remain, and then free the lock. e.g. something like synchronized(mutex) { auto tls = cast(MyObject)mySharedObject. //... do stuff... } // at this point, no thread-local references to mySharedObject // should // exist In this scenario, the types in question are not designed to be used with shared at all. They're designed to be thread-local. So, if they're marked as shared, they're basically useless except when you protect them with a mutex and correctly cast away shared in order to operate on the object while it's protected by the mutex and therefore is thread-safe. 3. An object is designed to be used as shared. In this case, it can have shared member functions, and they can be called on shared objects, but then internally, the object has to deal with properly managing shared. It either uses atomics and/or uses mutexes as in #2 - it's just that in this case, it's done internally by the object rather than the programmer using the object. synchronized classes are supposed to help with this particular case, but unfortunately, they're not fully implemented, so they don't currently help. But either way, the concept is still the same. You have on object that is designed to work with shared and deals with all of the appropriate protections internally. So, those are your three options. In the case of getopt, if you want to use shared, you basically have to use #2. It's not dealing with a basic type like an int or pointer, so atomics aren't going to work, and it's not designed to work with shared. So, if you want to do anything with getopt and shared, you're going to have to protect it with a mutex. That being said, I have to say that getopt seems like a really weird choice for wanting to do anything with shared. You normally call it immediately at the beginning of the program before doing anything with threads. The results might then be passed on to other threads via std.concurrency or through shared variables, but I wouldn't think that it would make a lot of sense to try and used getopt from more than one thread. - Jonathan M Davis
Re: getOpt with shared
On Friday, 11 May 2018 at 17:25:44 UTC, Danny Arends wrote: Hey all, I have been working on creating a multi-threaded application, so I have a shared configuration object which hold several command line parameters (which I fill using getopt). The problem is that I get deprecation warnings when trying to set numerical values: /usr/include/dmd/phobos/std/getopt.d(895,36): Deprecation: read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(*receiver, 1) instead. using getopt with a shared object and boolean values seems completely broken: /usr/include/dmd/phobos/std/getopt.d(895,34): Error: operation not allowed on bool *receiver += 1 /usr/include/dmd/phobos/std/getopt.d(751,46): Error: template instance `std.getopt.handleOption!(shared(bool)*)` error instantiating /usr/include/dmd/phobos/std/getopt.d(435,15):6 recursive instantiations from here: getoptImpl!(string, shared(string)*, string, shared(string)*, string, shared(VSync)*, string, shared(ulong)*, string, shared(bool)*, string, shared(Verbose)*) Is getopt not supposed to be used with shared structs ? small example: import std.getopt : getopt; struct Settings { size_t myvalue = 0; } shared(Settings) config; int main(string[] args) { getopt(args, "m|myvalue", &(config.myvalue)); return(0); } Changing size_t to bool, results in the compilation error mentioned in the previous post
getOpt with shared
Hey all, I have been working on creating a multi-threaded application, so I have a shared configuration object which hold several command line parameters (which I fill using getopt). The problem is that I get deprecation warnings when trying to set numerical values: /usr/include/dmd/phobos/std/getopt.d(895,36): Deprecation: read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(*receiver, 1) instead. using getopt with a shared object and boolean values seems completely broken: /usr/include/dmd/phobos/std/getopt.d(895,34): Error: operation not allowed on bool *receiver += 1 /usr/include/dmd/phobos/std/getopt.d(751,46): Error: template instance `std.getopt.handleOption!(shared(bool)*)` error instantiating /usr/include/dmd/phobos/std/getopt.d(435,15):6 recursive instantiations from here: getoptImpl!(string, shared(string)*, string, shared(string)*, string, shared(VSync)*, string, shared(ulong)*, string, shared(bool)*, string, shared(Verbose)*) Is getopt not supposed to be used with shared structs ?
Re: pointer to object resolution
On 5/11/18 8:53 AM, Alex wrote: This behaves differently, w.r.t. to an arbitrary method, like "operator". Why? Is there any workaround? operators don't follow pointers. Imagine if you had a struct that overloads "+" and then you wanted to use pointer arithmetic, but instead it called ptr.opBinary. The workaround is to dereference the pointer. e.g. 42 in *sptr; -Steve
Re: Why are deprecated aliases considered equal for resolution?
On Friday, May 11, 2018 14:02:22 Nicholas Wilson via Digitalmars-d-learn wrote: > - > module a; > > struct foo {} > > deprecated alias bar = foo; > > -- > module b; > struct bar {}; > > > --- > module c; > > import a; > import b; > > void baz(bar b) {} > > Error: `a.bar` at source/a.d(5,1) conflicts with `b.bar` at > .b.d(2,1) > > I would have thought the undeprecated alias would have been used. As I understand it, the only effect that deprecated really has is that you get a message printed telling you that the symbol is deprecated if it's used in undeprecated code. And that being the case, it definitely wouldn't affect something like overload resolution. And if you think about it, making deprecated affecting things like overload resolution could get pretty risky. Remember that the whole idea here is that a symbol is deprecated so that folks will stop using it, but you don't want code to break because of it. If anything behaves differently, then it risks code breakage, and that's exactly what you were trying to avoid by deprecating the symbol rather than just removing it. So, in general, when something is deprecated, we get to continue to live with the negatives of having it around - it's just that it discourages its use in new code and encourages people to stop using that symbol. So, when the symbol is removed, the only code that breaks should be unmaintained code that wasn't updated appropriately. But in the interim, it's still there causing symbol conflicts and whatnot, and I don't see how it could be otherwise without risking code breakage simply due to deprecation, and we really don't want that. It's disruptive enough as it is just to tell folks to stop using a symbol even if nothing breaks as long as the symbol is still around. - Jonathan M Davis
Why are deprecated aliases considered equal for resolution?
- module a; struct foo {} deprecated alias bar = foo; -- module b; struct bar {}; --- module c; import a; import b; void baz(bar b) {} Error: `a.bar` at source/a.d(5,1) conflicts with `b.bar` at .b.d(2,1) I would have thought the undeprecated alias would have been used.
Re: msgpack link failure - non-transitive pragma(lib)?
On Friday, 11 May 2018 at 12:53:08 UTC, Basile B. wrote: On Friday, 11 May 2018 at 12:35:52 UTC, TED_996 wrote: [...] Yeah, right guess in the title ;) you have to put the "pragma lib" again. Take the use of "pragma lib" in the binding as an information saying "you have to do this too". Sorry for double posting, but I find what you wrote hard to believe, especially since DCD, which uses msgpack, has no pragma(lib "ws2_32") in it. Can you cite a source, please?
Re: msgpack link failure - non-transitive pragma(lib)?
On Friday, 11 May 2018 at 12:53:08 UTC, Basile B. wrote: On Friday, 11 May 2018 at 12:35:52 UTC, TED_996 wrote: [...] Yeah, right guess in the title ;) you have to put the "pragma lib" again. Take the use of "pragma lib" in the binding as an information saying "you have to do this too". Okay, well, this information is nowhere to be seen (except *maybe* if you know where to look for). Besides, how am I supposed to know what every lib is using, including transitivity? There has to be a better way, right? A compiler warning? Maybe even a passing mention in the docs anywhere? (nowhere on this page, for example: https://dlang.org/spec/pragma.html, or on the msgpack page, or anywhere.)
pointer to object resolution
Hi all, I'm sure, I didn't find something obvious, but: Given this: ´´´ void main() { auto s = S(); s.operator; assert(s.myOp(42)); assert(42 in s); auto sptr = new S(); sptr.operator; assert(sptr.myOp(42)); //assert(42 in sptr); //<-- does not compile } struct S { void operator() const { assert(true); } bool opBinaryRight(string op)(size_t input) const if(op == "in") { return true; } bool myOp(size_t input) { return input in this; } } ´´´ The last line in the main does not compile with the message source/app.d(9,9): Error: incompatible types for `(42) in (sptr)`: `int` and `S*` This behaves differently, w.r.t. to an arbitrary method, like "operator". Why? Is there any workaround?
Re: msgpack link failure - non-transitive pragma(lib)?
On Friday, 11 May 2018 at 12:35:52 UTC, TED_996 wrote: I've been trying to debug this for a long time now. I am trying to build one of the msgpack examples (examples/upacker_foreach.d) and the linking failed. I have since succeeded and I'm trying to find out if this is intended behavior or a bug in D (not msgpack, I think). TL;DR: it seems to me like the pragma(lib, "ws2_32"); in core.sys.windows.winsock2, imported in msgpack.common, imported in msgpack (package.d), imported in my source files, does not hold; this was fixed when I added the pragma in my source file too. Versions: Windows 10, dmd 2.080.0, dub 1.9.0 The dub build output: Performing "debug" build using D:\D\dmd2\windows\bin\dmd.exe for x86. msgpack-d 1.0.0-beta.6: target for configuration "library" is up to date. hw ~master: building configuration "application"... Linking... OPTLINK (R) for Win32 Release 8.00.17 Copyright (C) Digital Mars 1989-2013 All rights reserved. http://www.digitalmars.com/ctg/optlink.html .dub\build\application-debug-windows-x86-dmd_2080-1E3111031ACEC4AEF53C62127331208A\hw.obj(hw) Error 42: Symbol Undefined _ntohl@4 .dub\build\application-debug-windows-x86-dmd_2080-1E3111031ACEC4AEF53C62127331208A\hw.obj(hw) Error 42: Symbol Undefined _ntohs@4 Error: linker exited with status 2 D:\D\dmd2\windows\bin\dmd.exe failed with exit code 1. dub.json: { "name": "hw", "authors": [ "ted_996" ], "description": "A minimal D application.", "copyright": "Copyright © 2018, ted_996", "license": "proprietary", "dependencies": { "msgpack-d": ">=1.0.0-beta.6" } } After some digging, I found that other binaries that used msgpack (DCD) were importing ws2_32, but it seemed like my binary was not. Both debug and release and x86 and x64 versions were failing to link; msgpack built fine but probably only the msgpack.lib file (no final link). However, when I (counter-intuitively, for me) added pragma(lib, "ws2_32"); to my own source files, it built successfully. Should that have been necessary? it was not in any examples. What gives? Thanks! Yeah, right guess in the title ;) you have to put the "pragma lib" again. Take the use of "pragma lib" in the binding as an information saying "you have to do this too".
msgpack link failure - non-transitive pragma(lib)?
I've been trying to debug this for a long time now. I am trying to build one of the msgpack examples (examples/upacker_foreach.d) and the linking failed. I have since succeeded and I'm trying to find out if this is intended behavior or a bug in D (not msgpack, I think). TL;DR: it seems to me like the pragma(lib, "ws2_32"); in core.sys.windows.winsock2, imported in msgpack.common, imported in msgpack (package.d), imported in my source files, does not hold; this was fixed when I added the pragma in my source file too. Versions: Windows 10, dmd 2.080.0, dub 1.9.0 The dub build output: Performing "debug" build using D:\D\dmd2\windows\bin\dmd.exe for x86. msgpack-d 1.0.0-beta.6: target for configuration "library" is up to date. hw ~master: building configuration "application"... Linking... OPTLINK (R) for Win32 Release 8.00.17 Copyright (C) Digital Mars 1989-2013 All rights reserved. http://www.digitalmars.com/ctg/optlink.html .dub\build\application-debug-windows-x86-dmd_2080-1E3111031ACEC4AEF53C62127331208A\hw.obj(hw) Error 42: Symbol Undefined _ntohl@4 .dub\build\application-debug-windows-x86-dmd_2080-1E3111031ACEC4AEF53C62127331208A\hw.obj(hw) Error 42: Symbol Undefined _ntohs@4 Error: linker exited with status 2 D:\D\dmd2\windows\bin\dmd.exe failed with exit code 1. dub.json: { "name": "hw", "authors": [ "ted_996" ], "description": "A minimal D application.", "copyright": "Copyright © 2018, ted_996", "license": "proprietary", "dependencies": { "msgpack-d": ">=1.0.0-beta.6" } } After some digging, I found that other binaries that used msgpack (DCD) were importing ws2_32, but it seemed like my binary was not. Both debug and release and x86 and x64 versions were failing to link; msgpack built fine but probably only the msgpack.lib file (no final link). However, when I (counter-intuitively, for me) added pragma(lib, "ws2_32"); to my own source files, it built successfully. Should that have been necessary? it was not in any examples. What gives? Thanks!
Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait
On Thursday, 10 May 2018 at 19:14:39 UTC, Meta wrote: So it looks like disabling a struct's postblit actually counts as having a __postblit and __xpostblit function (don't ask me why), in addition to a construction and opAssign... no idea why, and maybe this is a bug, but I bet there's a good reason for it. https://issues.dlang.org/show_bug.cgi?id=18628 -Johan