[Issue 17766] Wrong choice of generic mutable/const/immutable methods
https://issues.dlang.org/show_bug.cgi?id=17766 alexandru.ermic...@gmail.com changed: What|Removed |Added CC||alexandru.ermic...@gmail.co ||m --- Comment #1 from alexandru.ermic...@gmail.com --- This is not the only case, here is another case of wrong selection: -- class Mquartz(T, Z) { Z pass(T component) const { "Mutable pass".writeln; return component.z; } const(Z) pass(const T component) const { "Const pass".writeln; return component.z; } const(Z) pass(immutable T component) const { "Immutable pass".writeln; return component.z; } const(Z) pass(inout T component) const { "Inout pass".writeln; return component.z; } } struct V { int z; } void main() { auto m = new Mquartz!(V, typeof(V.z)); // V v = V(21); // writeln(m.pass(v)); writeln(m.pass(V(20))); writeln(m.pass(const(V)(20))); writeln(m.pass(immutable(V)(20))); writeln(m.pass(inout(V)(20))); } - Current logic will select only const version with const argument instead of selecting right ones: - Const pass 20 Const pass 20 Const pass 20 Const pass 20 - The overload selection logic works as expected only if m is const, then response will as expected: - Mutable pass 20 Const pass 20 Immutable pass 20 Inout pass 20 - --
Re: D Binding to GUI libraries
On 2018-10-22 12:06, Russel Winder wrote: Jacob, GitHub is currently making a total mess for me of our conversation on Issue 42, I see stuff then it goes away. Apologies if I have made a mess of that conversation for you. Yeah, I noticed that. GitHub had/still having some major issues [1]. Swing is, but JavaFX is now OpenJFX and a separate think to OpenJDK. JavaFX is shipped with Java 8 at least, the one I was running (I'm a bit behind). Indeed. But compared to Qt (and maybe GTK+ and wxWidgets) it is very much a niche framework. Why do you think that, besides from being written in Java? Or it has many native GUIs whereas Windows and macOS offer no choice? Haha, I guess you can look at it that way. I still think getting a Qt binding for D à la PyQt, PySide2, Rust-Qt, i.e. automated with minimal manual tweeks, would be a Very Good Thing™ for the D pitch in the desktop GUI applications arena. Sure, different toolkits for different needs. [1] https://status.github.com/messages -- /Jacob Carlborg
Re: D Binding to GUI libraries
On 2018-10-21 22:31, Patrick Schluter wrote: I like it and I'm looking forward that it gets beyond swt 3.4. I ported my Java GUI SWT program to D and it was a breeze to do. I didn't even require to change the structure of the app and the class hierarchy. There was only the file and string handling that I had to change, in fact make so much more readable and efficient. There were some difficulties because of compiler issues in version 2.7x, but those were resolved and everything went smooth after that. That's great to hear :) -- /Jacob Carlborg
[Issue 19326] .tupleof sidesteps protection attributes
https://issues.dlang.org/show_bug.cgi?id=19326 Jacob Carlborg changed: What|Removed |Added CC||d...@me.com --- Comment #1 from Jacob Carlborg --- I don't consider this a bug, I consider this a feature. --
Re: Which Docker to use?
On 2018-10-21 20:45, Jon Degenhardt wrote: My comment painted too broad a brush. I had forgotten how specific the issue I saw was. Apologies for the confusion. The issue that caused me to go to Ubuntu 16.04 had to do with uncaught exceptions when using LTO with the gold linker and LDC 1.5. Problem occurred with 14.04, but not 16.04. I should go back and retest on Ubuntu 14.04 with a more recent LDC, it may well have been corrected. The issue thread is here: https://github.com/ldc-developers/ldc/issues/2390. Ah, that might be the reason. I am not using LTO. You might want to try a newer version of LDC as well since 1.5 is quite old now. -- /Jacob Carlborg
Re: D Binding to GUI libraries
On Mon, 2018-10-22 at 16:23 +, Gregor Mückl via Digitalmars-d wrote: > […] > It's easy to go and proclaim a strategic goal such as this. What > actually matters is execution. And that requires some serious > developer time that someone (ideally a whole team) needs to > invest. I don't see this happening without some equally serious > financial backing. Agreed. And sadly a common facet of the D situation: all words and no action – including from me. > I, for one, won't have any time to work on such a thing in the > foreseeable future. In principle I could, but only as part of a team. This is not a one person project. > Does anyone have experience with bounty programs? I envision one > where bounties get posted with an open pool for each one. That > is, if you agree that one task should be done, you can put > additional money into its pool and make that particular bounty > more attractive. It won't help attract professional developers > but it might nudge some hobbyists to earn some money while taking > on an interesting challenge. This might work for all the small > things around D that lots of D users don't like and want improved. I am not in a position to receive income, so I work for love or large payments to charities I nominate. Currently I am a bit overly obsessed with DVB and DAB+ using GStreamer, so mostly programming for love – and hence very fickle about doing stuff that requires commitment. The QtGStreamer has just been declared unmaintained :-( -- Russel. === Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Roadm: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk signature.asc Description: This is a digitally signed message part
Re: shared - i need it to be useful
On Mon, Oct 22, 2018 at 6:00 AM Timon Gehr via Digitalmars-d wrote: > > On 22.10.18 12:26, Timon Gehr wrote: > > --- > > module borked; > > > > void atomicIncrement(int* p)@system{ > > import core.atomic; > > atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); > > } > > > > struct Atomic(T){ > > private T val; > > void opUnary(string op : "++")() shared @trusted { > > atomicIncrement(cast(T*)); > > } > > } > > void main()@safe{ > > Atomic!int i; > > auto a=&[i][0];// was: Atomic!int* a = > > import std.concurrency; > > spawn((shared(Atomic!int)* a){ ++*a; }, a); > > ++i.val; // race > > } > > --- > > Obviously, this should have been: > > --- > module borked; > > void atomicIncrement(int*p)@system{ > import core.atomic; > atomicOp!"+="(*cast(shared(int)*)p,1); > } > struct Atomic(T){ > private T val; > void opUnary(string op:"++")()shared @trusted{ > atomicIncrement(cast(T*)); > } > } > void main()@safe{ > auto a=new Atomic!int; > import std.concurrency; > spawn((shared(Atomic!int)* a){ ++*a; }, a); > ++a.val; // race > } > --- > > (I was short on time and had to fix Manu's code because it was not > actually compilable.) Nitpick; atomicOp does not receive a shared arg under my proposal, it's not a threadsafe function by definition as discussed a few times.
Re: shared - i need it to be useful
On Mon, Oct 22, 2018 at 4:50 AM Stanislav Blinov via Digitalmars-d wrote: > > On Monday, 22 October 2018 at 00:22:19 UTC, Manu wrote: > > > No no, they're repeated, not scattered, because I seem to have > > to keep repeating it over and over, because nobody is reading > > the text, or perhaps imaging there is a lot more text than > > there is. > > ... > > You mean like every post in opposition which disregards the > > rules and baselessly asserts it's a terrible idea? :/ > > ... > > I responded to your faulty program directly with the correct > > program, and you haven't acknowledged it. Did you see it? > > Right back at you. > > Quote: > > I think this is a typical sort of construction: > > struct ThreadsafeQueue(T) > { >void QueueItem(T*) shared; >T* UnqueueItem() shared; > } > > struct SpecialWorkList > { >struct Job { ... } > >void MakeJob(int x, float y, string z) shared // <- any thread > may > produce a job >{ > Job* job = new Job; // <- this is thread-local > PopulateJob(job, x, y, z); // <- preparation of a job might be > complex, and worthy of the SpecialWorkList implementation > > jobList.QueueItem(job); // <- QueueItem encapsulates > thread-safety, no need for blunt casts >} > >void Flush() // <- not shared, thread-local consumer >{ > Job* job; > while (job = jobList.UnqueueItem()) // <- it's obviously safe > for > a thread-local to call UnqueueItem even though the implementation > is > threadsafe > { >// thread-local dispatch of work... >// perhaps rendering, perhaps deferred destruction, perhaps > deferred resource creation... whatever! > } >} > >void GetSpecialSystemState() // <- this has NOTHING to do with > the > threadsafe part of SpecialWorkList >{ > return os.functionThatChecksSystemState(); >} > >// there may be any number of utility functions that don't > interact > with jobList. > > private: >void PopulateJob(ref Job job, ...) >{ > // expensive function; not thread-safe, and doesn't have any > interaction with threading. >} > >ThreadsafeQueue!Job jobList; > } > > > This isn't an amazing example, but it's typical of a thing that's > mostly thread-local, and only a small controlled part of it's > functionality is thread-safe. > The thread-local method Flush() also deals with thread-safety > internally... because it flushes a thread-safe queue. > > All thread-safety concerns are composed by a utility object, so > there's no need for locks, magic, or casts here. > > EndQuote; > > The above: > 1) Will not compile, not currently, not under your proposal > (presumably you forgot in frustration to cast before calling > PopulateJob?..) I did correct that line (along with an apology) on my very next post; it would probably be a member of Job... or any manner of other code. That is the least interesting line in the program > 2) Does not in any way demonstrate a practical @safe application > of an implicit conversion. As I wrote in the original response to > that code, with that particular code it seems more like you just > need forwarding methods that call `shared` methods under the hood > (i.e. MakeJob), and it'd be "nice" if you didn't have to write > those and could just call `shared` MakeJob on an un-`shared` > reference directly. But these are all assumptions without seeing > the actual usage. > > Please just stop acting like everyone here is opposing *you*. You're right, it's mostly you. > All > you're doing is dismissing everyone with a "nuh-huh, you no > understand, you bad". If it was just me, fine, it would mean I'm > dumb and not worthy of this discussion. But this isn't the case, > which means *you are not getting your point across*. And yet > instead of trying to fix that, you're getting all snarky. I mean, it's fair, but it's pretty bloody hypocritical coming from you! I think it's fair to point out that your high-frequency, persistent, and unwavering hostility from post #1 across all my recent threads (at least, until I told you to GF) is the primary reason I'm frustrated here. You can own part responsibility for my emotion.
[Issue 18896] extern(C++) always mangles classes as pointer
https://issues.dlang.org/show_bug.cgi?id=18896 --- Comment #1 from Mathias LANG --- Renamed to make it a bit more generic. This is also a problem when `ref` is used for passing the class around. E.g. `foo(MyClass&)` cannot be represented in D, which is very limiting. --
[Issue 18896] extern(C++) always mangles classes as pointer
https://issues.dlang.org/show_bug.cgi?id=18896 Mathias LANG changed: What|Removed |Added CC||pro.mathias.l...@gmail.com Summary|extern(C++) template with |extern(C++) always mangles |class argument mangling |classes as pointer --
[Issue 19260] extern(C++) `T* const` mangling
https://issues.dlang.org/show_bug.cgi?id=19260 Mathias LANG changed: What|Removed |Added CC||pro.mathias.l...@gmail.com --- Comment #7 from Mathias LANG --- I strongly agree with Kinke here and think we should not pursue mangling head const, as it's already possible to do it with a small hack (and it's a one-time cost). --
Re: shared - i need it to be useful
On Mon, Oct 22, 2018 at 3:30 AM Timon Gehr via Digitalmars-d wrote: > > On 22.10.18 02:54, Manu wrote: > > On Sun, Oct 21, 2018 at 5:40 PM Timon Gehr via Digitalmars-d > > wrote: > >> > >> On 21.10.18 21:04, Manu wrote: > >>> On Sun, Oct 21, 2018 at 12:00 PM Timon Gehr via Digitalmars-d > >>> wrote: > > On 21.10.18 17:54, Nicholas Wilson wrote: > > > >> As soon as that is done, you've got a data race with the other > >> existing unshared aliases. > > > > You're in @trusted code, that is the whole point. The onus is on the > > programmer to make that correct, same with regular @safe/@trusted@system > > code. > > Not all of the parties that participate in the data race are in @trusted > code. The point of @trusted is modularity: you manually check @trusted > code according to some set of restrictions and then you are sure that > there is no memory corruption. > > Note that you are not allowed to look at any of the @safe code while > checking your @trusted code. You will only see an opaque interface to > the @safe code that you call and all you know is that all the @safe code > type checks according to @safe rules. Note that there might be an > arbitrary number of @safe functions and methods that you do not see. > > Think about it this way: you first write all the @trusted and @system > code, and some evil guy who does not like you comes in after you looks > at your code and writes all the @safe code. If there is any memory > corruption, it will be your fault and you will face harsh consequences. > Now, design the @safe type checking rules. It won't be MP! > > Note that there may well be a good way to get the good properties of MP > without breaking the type system, but MP itself is not good because it > breaks @safe. > >>> > >>> Show me. Nobody has been able to show that yet. I'd really like to know > >>> this. > >>> > >> > >> I just did, > > > > There's no code there... just a presumption that the person who wrote > > the @trusted code did not deliver the promise they made. > > ... > > Yes, because there is no way to write @trusted code that holds its > promise while actually doing something interesting in multiple threads > if @safe code can implicitly convert from unshared to shared. How do my examples prior fail to hold their promise? struct S { private int x; void method() shared @trusted { /* safely manipulate x */ } } How can you not trust that function? How can a 3rd party invalidate that functions promise? `x` is inaccessible. S can be thread-local or shared as much as you like, and it's safe, and I don't know how a 3rd party could @safely undermine that? > >> but if you really need to, give me a non-trivial piece of> correct > >> multithreaded code that accesses some declared-unshared field > >> from a shared method and I will show you how the evil guy would modify > >> some @safe code in it and introduce race conditions. It needs to be your > >> code, as otherwise you will just claim again that it is me who wrote bad > >> @trusted code. > > > > You can pick on any of my prior code fragments. They've all been ignored so > > far. > > > > I don't want "code fragments". Show me the real code. > > I manually browsed through posts now (thanks a lot) and found this > implementation: > > struct Atomic(T){ >void opUnary(string op : "++")() shared { atomicIncrement(); } >private T val; > } > > This is @system code. There is no @safe or @trusted here, so I am > ignoring it. > > > Then I browsed some more, because I had nothing better to do, and I > found this. I completed it so that it is actually compilable, except for > the unsafe implicit conversion. > > Please read this code, and then carefully read the comments below it > before you respond. I will totally ignore any of your answers that > arrive in the next two hours. > > --- > module borked; > > void atomicIncrement(int* p)@system{ > import core.atomic; > atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); > } > > struct Atomic(T){ > private T val; > void opUnary(string op : "++")() shared @trusted { > atomicIncrement(cast(T*)); > } > } > void main()@safe{ > Atomic!int i; > auto a=&[i][0];// was: Atomic!int* a = > import std.concurrency; > spawn((shared(Atomic!int)* a){ ++*a; }, a); > ++i.val; // race > } > --- > > > Oh no! The author of the @trusted function (i.e. you) did not deliver on > the promise they made! > > Now, before you go and tell me that I am stupid because I wrote bad > code, consider the following: > > - It is perfectly @safe to access private members from the same module. > > - You may not blame the my @safe main function for the problem. It is > @safe, so it cannot be blamed for UB. Any UB is the result of a bad > @trusted function, a compiler bug, or hardware failure. > > - The only @trusted function in this
[Issue 15473] C++ mangling problem
https://issues.dlang.org/show_bug.cgi?id=15473 Mathias LANG changed: What|Removed |Added CC||pro.mathias.l...@gmail.com --- Comment #7 from Mathias LANG --- Do you still see this ? Without a proper way to reproduce, I don't know what we can do about this bug. --
[Issue 15387] slice in extern(C++) ICE's
https://issues.dlang.org/show_bug.cgi?id=15387 Mathias LANG changed: What|Removed |Added Status|NEW |RESOLVED CC||pro.mathias.l...@gmail.com Resolution|--- |WORKSFORME --- Comment #2 from Mathias LANG --- It does not crash the compiler anymore, but print ICE. See https://issues.dlang.org/show_bug.cgi?id=18716 --
[Issue 17975] D produces mangling incompatible with C++
https://issues.dlang.org/show_bug.cgi?id=17975 Mathias LANG changed: What|Removed |Added Status|NEW |RESOLVED CC||pro.mathias.l...@gmail.com Resolution|--- |INVALID --- Comment #2 from Mathias LANG --- Indeed, it's a transitive const issue. We should properly document how to bind C++ to D (as not all code can be), but that's another issue. Closing as invalid. --
[Issue 16479] Missing substitution while mangling C++ template parameter for functions
https://issues.dlang.org/show_bug.cgi?id=16479 Mathias LANG changed: What|Removed |Added CC||timothee.co...@gmail.com --- Comment #8 from Mathias LANG --- *** Issue 16944 has been marked as a duplicate of this issue. *** --
[Issue 16944] extern(C++) with template produces wrong mangleof
https://issues.dlang.org/show_bug.cgi?id=16944 Mathias LANG changed: What|Removed |Added Status|NEW |RESOLVED CC||pro.mathias.l...@gmail.com Resolution|--- |DUPLICATE --- Comment #1 from Mathias LANG --- Duplicate of 16479 (for which there is a pull) *** This issue has been marked as a duplicate of issue 16479 *** --
[Issue 15970] C++ mangling of templated arg type
https://issues.dlang.org/show_bug.cgi?id=15970 Mathias LANG changed: What|Removed |Added Status|REOPENED|RESOLVED CC||pro.mathias.l...@gmail.com Resolution|--- |DUPLICATE --- Comment #5 from Mathias LANG --- Marking as a duplicate of 16479, which is older, but for which there is a PR. I just tried it with PR 8455 and it gets mangled correctly: ``` ../../install/osx/bin/dmd -c lol.d; nm lol.o | c++filt [...] 04c8 S A::foo_template(int) 0040 S A::foo_template(int) (.eh) 04d0 S A::foo_incorrect(Symbol*) 0068 S A::foo_incorrect(Symbol*) (.eh) ``` *** This issue has been marked as a duplicate of issue 16479 *** --
[Issue 16479] Missing substitution while mangling C++ template parameter for functions
https://issues.dlang.org/show_bug.cgi?id=16479 Mathias LANG changed: What|Removed |Added CC||jbc.enge...@gmail.com --- Comment #7 from Mathias LANG --- *** Issue 15970 has been marked as a duplicate of this issue. *** --
Re: D Binding to GUI libraries
On Sunday, 21 October 2018 at 17:15:03 UTC, Russel Winder wrote: On Sun, 2018-10-21 at 08:42 +, Paolo Invernizzi via Digitalmars-d wrote: […] Linux is not only the desktop, and Qt simply dominates in industrial, medical and automation sector, that's where the money is. Qt is pushing strongly on the embedded marked, bare metal or linux (kernel) based... Which means that D not having a good play in the Qt space is a big barrier to adoption. This means it ought to be a strategic goal to have a (and I think I mean one here) D binding to Qt and QML. It's easy to go and proclaim a strategic goal such as this. What actually matters is execution. And that requires some serious developer time that someone (ideally a whole team) needs to invest. I don't see this happening without some equally serious financial backing. I, for one, won't have any time to work on such a thing in the foreseeable future. Does anyone have experience with bounty programs? I envision one where bounties get posted with an open pool for each one. That is, if you agree that one task should be done, you can put additional money into its pool and make that particular bounty more attractive. It won't help attract professional developers but it might nudge some hobbyists to earn some money while taking on an interesting challenge. This might work for all the small things around D that lots of D users don't like and want improved.
Re: assigment to null class object member compiled? is this a bug?
On Friday, 19 October 2018 at 06:53:32 UTC, dangbinghoo wrote: why the code bellow compiles? D compilers are allowed to make that an error, but it might not. With the current implementation, dmd that.d will compile, but dmd -O that.d will fail with an error. Yes, turning on optimizations happens to catch the null flow at compile time. It is just a matter of compiler implementation happening to catch it or not.
Re: D Binding to GUI libraries
On Mon, 22 Oct 2018 03:49:44 -0400, Nick Sabalausky (Abscissa) wrote: > So I'm honestly *shocked* to hear this. I NEVER would've guessed. I'm > pretty sold on rolling-release at this point, but I'm intrigued enough > that I'm gonna have to give the latest Ubuntu a try, at least in a VM. The latest Ubuntu has Unity 7 as an option and defaults to GNOME, so you'd have to compile a Unity 8 prerelease from source.
Re: assigment to null class object member compiled? is this a bug?
On Monday, 22 October 2018 at 01:39:48 UTC, dangbinghoo wrote: On Friday, 19 October 2018 at 09:08:32 UTC, Vijay Nayar wrote: Technically the code you have is syntactically correct. You are permitted to create a class variable without assigning it to a class object. (Assigning it to a class object would look like "A a = new A();") Which section of The D Programming Language book makes you think this would not compile? I have the book as well, but I'm not quite sure what part of the book you're referring to. the section 6.2, which is --- A a; a.x = 5; --- the book explained this should be refused to compile. thanks! -- dangbinghoo You are wrong, actually: In the book, site 179 it states: "If you try to access a non-static member of a reference and the compiler can prove statically that the reference would definitely be null, it will refuse to compile the code." But the compiler is not able to prove that the reference is definitely null. At least in this case, with compiler, I think of. That's why it called runtime error.
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 14:31:28 UTC, Timon Gehr wrote: On 22.10.18 16:09, Simen Kjærås wrote: On Monday, 22 October 2018 at 13:40:39 UTC, Timon Gehr wrote: module reborked; import atomic; void main()@safe{ auto a=new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++a.tupleof[0]; } Finally! Proof that MP is impossible. On the other hand, why the hell is that @safe? It breaks all sorts of guarantees about @safety. At a minimum, that should be un-@safe. Filed in bugzilla: https://issues.dlang.org/show_bug.cgi?id=19326 -- Simen Even if this is changed (and it probably should be), it does not fix the case where the @safe function is in the same module. I don't think it is desirable to change the definition of @trusted such that you need to check the entire module if it contains a single @trusted function. If I can break safety of some (previously correct) code by editing only @safe code, then that's a significant blow to @safe. I think we need a general way to protect data from being manipulated in @safe code in any way, same module or not. What do you mean by 'previously correct'? struct Array(T) { @safe: private int* ptr; private int length; @disable this(); this(int n) @trusted { ptr = new int[n].ptr; length = n; foreach (ref e; ptr[0..length]) e = 123; } @trusted ref int get(int idx) { assert(idx < length); return ptr[idx]; } } unittest { auto s = Array!int(1); assert(s.get(0) == 123); } Is this correct code? What if I add this: @safe void bork(T)(ref Array!T s) { s.length *= 2; } unittest { auto s = Array!int(1); bork(s); assert(s.get(1) == 123); // Out of bounds! } -- Simen
Re: Manu's `shared` vs the @trusted promise
On Monday, 22 October 2018 at 11:24:27 UTC, Dukc wrote: Frankly, this does not sound credible. According to this rationale, array access should be @system too, because it relies on the array not giving direct access to its length to the user, which would also in itself be @safe. For reading, its a size_t so can be done with atomics, writing OTOH is a @property that calls a function to reallocate if ned be. Reallocation obviously needs to be locked.
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:22:19 UTC, Manu wrote: On Sun, Oct 21, 2018 at 2:35 PM Walter Bright via Digitalmars-d wrote: On 10/21/2018 2:08 PM, Walter Bright wrote: > On 10/21/2018 12:20 PM, Nicholas Wilson wrote: >> Yes, but the problem you describe is arises from implicit >> conversion in the other direction, which is not part of the >> proposal. > > It's Manu's example. Then I don't know what the proposal is. Pieces of it appear to be scattered over numerous posts, mixed in with other text, No no, they're repeated, not scattered, because I seem to have to keep repeating it over and over, because nobody is reading the text, or perhaps imaging there is a lot more text than there is. I can go look at the original post - and I have - but while it may strictly speaking contain all the information I need, the amount of time and brain power it would take for me to comprehend the consequences is pretty large. I assume you have done a lot of that work already and could save everyone a lot of time by putting together a quick document that covers some of that, with good examples. I'm not going to read {1,2,3}00 messages full of irritated bidirectional miscommunication to try and understand this unless I really have to, and I assume others feel similarly.
Re: shared - i need it to be useful
On 22.10.18 16:09, Simen Kjærås wrote: On Monday, 22 October 2018 at 13:40:39 UTC, Timon Gehr wrote: module reborked; import atomic; void main()@safe{ auto a=new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++a.tupleof[0]; } Finally! Proof that MP is impossible. On the other hand, why the hell is that @safe? It breaks all sorts of guarantees about @safety. At a minimum, that should be un-@safe. Filed in bugzilla: https://issues.dlang.org/show_bug.cgi?id=19326 -- Simen Even if this is changed (and it probably should be), it does not fix the case where the @safe function is in the same module. I don't think it is desirable to change the definition of @trusted such that you need to check the entire module if it contains a single @trusted function. If I can break safety of some (previously correct) code by editing only @safe code, then that's a significant blow to @safe. I think we need a general way to protect data from being manipulated in @safe code in any way, same module or not.
Re: Manu's `shared` vs the @trusted promise
On Monday, 22 October 2018 at 11:24:27 UTC, Dukc wrote: Frankly, this does not sound credible. According to this rationale, array access should be @system too, because it relies on the array not giving direct access to its length to the user, which would also in itself be @safe. Arrays are a language builtin. As far as I'm aware, there isn't actually an struct defined in DRuntime for arrays. But maybe I'm wrong. If there is, and if it uses a plain size_t for the length member, then it is breaking the strong @trusted promise, yes. But having existing exceptions to the rule doesn't mean that the rule is void. We could identify the existing exceptions as bugs and try to fix them. Or we could say that they're a necessary evil, but we don't want to add more evil. On the other hand, D could of course embrace a weaker @trusted/@safe. That would be up to Walter and Andrei, I guess. As far as I can tell from the other `shared` thread, Walter currently favors a strong @trusted.
Re: custom sorting of lists ?
On 10/19/18 3:58 PM, Carl Sturtivant wrote: On Friday, 19 October 2018 at 17:53:58 UTC, Stanislav Blinov wrote: On Friday, 19 October 2018 at 17:40:59 UTC, Carl Sturtivant wrote: If we imagine an Ordered Range being a finite Range of some kind with the additional property that its values are ordered (--- exact definition needed ---)... There's already a SortedRange: https://dlang.org/phobos/std_range.html#.SortedRange That's nice. So perhaps all this can be done in using the existing machinery in Phobos. Again, the benefit of linked lists here is we don't have to actually move any data, we are just rearranging pointers. We can certainly create a mergesort routine that works with any data types, as long as it has scratch space to move the data around. But that isn't as effective or efficient as a dedicated linked-list routine. -Steve
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:22:19 UTC, Manu wrote: On Sun, Oct 21, 2018 at 2:35 PM Walter Bright via Digitalmars-d wrote: Then I don't know what the proposal is. Pieces of it appear to be scattered over numerous posts, mixed in with other text, No no, they're repeated, not scattered, because I seem to have to keep repeating it over and over, because nobody is reading the text, or perhaps imaging there is a lot more text than there is. I've read every post on this thread and I also have the feeling that it's scattered. At the very least, I'm 90% confident I don't understand what it is you're proposing. Trust me, I'm trying. I believe that you have a proposal which you believe results in @safe multithreaded code. I don't understand how what I've read so far would accomplish that. I'm conviced that shared data shouldn't be allowed to be written to, but I haven't yet been convinced of anything else. I don't see how it's possible that implicit conversion from non-shared to shared can work at all. Yes, I know that in the proposal putting `shared` on anything makes it useless, but *somehow* that data gets to be used, even if it's by a @trusted function that casts away shared. At that point, nothing you do thread-safely to the shared data matters if you obtained the shared data from an implicit conversion. There may be many many aliases to it before it was converted, all of them able to write to that memory location believing it's not shared. And it would be @safe (but definitely not thread-safe) to do so! This has been explained a few times, by multiple people. I haven't seen anyone addressing this yet (it's possible it got lost in a sea of text). I don't even understand why it is you want to cast anything to shared anyway - that'd always be a code smell if I saw it during code review. If it's shared, type it as such. Or better yet, if you can just use immutable. I understand the frustration of not getting your point across. I would like to kindly point out that, if the replies have gotten to multiple dozen pages and several well-meaning people still don't get it, then the proposal probably isn't as simple as you believe it to be.
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 13:40:39 UTC, Timon Gehr wrote: module reborked; import atomic; void main()@safe{ auto a=new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++a.tupleof[0]; } Finally! Proof that MP is impossible. On the other hand, why the hell is that @safe? It breaks all sorts of guarantees about @safety. At a minimum, that should be un-@safe. Filed in bugzilla: https://issues.dlang.org/show_bug.cgi?id=19326 -- Simen
[Issue 19326] New: .tupleof sidesteps protection attributes
https://issues.dlang.org/show_bug.cgi?id=19326 Issue ID: 19326 Summary: .tupleof sidesteps protection attributes Product: D Version: D2 Hardware: x86 OS: Windows Status: NEW Severity: critical Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: simen.kja...@gmail.com module foo; struct S { private int i; } module bar; import foo; @safe unittest { S s; // Fails: struct `foo.S` member i is not accessible s.i++; // Fails: struct `foo.S` member i is not accessible __traits(getMember, s, "i")++; // Compiles just fine: s.tupleof[0]++; } This breaks guarantees about what's accessible from other modules, and can be used to break invariants relied on in @trusted code. At the very least, this should not be @safe. Related: issue 15371 --
Re: shared - i need it to be useful
On 22.10.18 15:26, Simen Kjærås wrote: Here's the correct version: module atomic; void atomicIncrement(int* p) @system { import core.atomic; atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); } struct Atomic(T) { // Should probably mark this shared for extra safety, // but it's not strictly necessary private T val; void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } - module unborked; import atomic; void main() @safe { auto a = new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); //++i.val; // Cannot access private member } Once more, Joe Average Programmer should not be writing the @trusted code in Atomic!T.opUnary - he should be using libraries written by people who have studied the exact issues that make multithreading hard. -- Simen module reborked; import atomic; void main()@safe{ auto a=new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++a.tupleof[0]; }
Re: shared - i need it to be useful
On 22.10.18 03:01, Manu wrote: On Sun, Oct 21, 2018 at 5:55 PM Timon Gehr via Digitalmars-d wrote: On 22.10.18 02:45, Manu wrote: On Sun, Oct 21, 2018 at 5:35 PM Timon Gehr via Digitalmars-d wrote: On 21.10.18 20:46, Manu wrote: Shared data is only useful if, at some point, it is read/written, presumably by casting it to unshared in @trusted code. As soon as that is done, you've got a data race with the other existing unshared aliases. If such a race is possible, then the @trusted function is not threadsafe, so it is not @trusted by definition. You wrote a bad @trusted function, and you should feel bad. ... I wonder where this "each piece of code is maintained by only one person and furthermore this is the only person that will suffer if the code has bugs" mentality comes from. It is very popular as well as obviously nonsense. The simplest way to guarantee that no unsafe access is possible is to use encapsulation to assure no unregulated access exists. This only works if untrusted programmers (i.e. programmers who are only allowed to write/modify @safe code) are not allowed to change your class. I.e. it does not work. Have you ever cracked open std::map and 'fixed' it because you thought it was bad? (Also, yes, some people do that because std::map does not provide an interface to augment the binary search tree.) Of course not. Same applies here. Nobody 'fixes' core.atomic.Atomic without understanding what they're doing. You are not proposing to let core.atomic.Atomic convert to shared implicitly, you are proposing to do that for all classes. You can always implicitly convert to shared. Yes, exactly what I said. Where did I ever say anything like that? I'm sure I've never said this. ??? I said that you are proposing to allow implicit conversions to shared for all classes, not only core.atomic.Atomic, and the last time you said it was the previous sentence of the same post. How do these transformations of what I've said keep happening? ... You literally said that nobody changes core.atomic.Atomic. Anyway, even if I bought that @safe somehow should not be checked within druntime (I don't), bringing up this example does not make for a coherent argument why implicit conversion to shared should be allowed for all classes. You seem to be stuck on the detail whether you can trust the @trusted author though... Again: the @safe author is the problem. I don't follow. The @safe author is incapable of doing threadsafety violation. They are capable of doing so as soon as you provide them a @trusted function that treats data as shared that they can access as unshared. They can only combine threadsafe functions. They can certainly produce a program that doesn't work, and they are capable of ordering issues, but that's not the same as data-race related crash bugs. Accessing private members of aggregates in the same module is @safe. tupleof is @safe too.
Re: Manu's `shared` vs the @trusted promise
On Monday, 22 October 2018 at 09:40:42 UTC, Manu wrote: On Mon, Oct 22, 2018 at 2:21 AM ag0aep6g via Digitalmars-d wrote: On 22.10.18 10:39, Simen Kjærås wrote: > On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote: [...] > It's invalid only if Atomic.badboy exists. I don't agree. I prefer the stronger @trusted. As far as I know, the stronger one is the current one. The current one has the critical weakness that it causes **EVERY USER** to write unsafe code, manually casting things to shared. Nope: --- auto list = /*new?*/ shared MyFancyLockFreeList(); --- If you want a `shared` something, create it as shared to begin with, there's no need to cast.
Re: We need an internal keyword.
On Monday, 22 October 2018 at 11:06:42 UTC, Jonathan M Davis wrote: On Monday, October 22, 2018 2:30:21 AM MDT Basile B. via Digitalmars-d wrote: On Monday, 22 October 2018 at 08:25:17 UTC, Andrea Fontana wrote: > Moreover: you're the author of the module so you're supposed > to know how it works and which members you should call or > not. - team - maintainer of a module written by someone that works elsewhere now. that's two cases where strict privacy can be optionally a thing avoiding wrong usage of private members within the scope of a module. Part of the point is that if the module is large enough that the folks working on the code can't actually keep track of what's in it, then it's too large, and as such, if you need to protect your class or struct members from the rest of the module, then it really should be in a separate module for the code to be properly maintainable anyway. Yes, having multiple people involved makes the problem worse (especially when some of them join the team later), but it doesn't fundamentally change the issue. If it changes anything, it simply makes the argument stronger for preferring smaller modules so that they're easier to digest. Personally, I've found that larger modules have worked just fine for me without having to worry about these sort of encapsulation issues. It simply isn't a problem, and I don't recall ever seeing a bug because of it. But anyone who's worried about it always has the option of simply going for smaller modules, and the encapsulation problem is already solved without making the language any more complicated. Plenty of folks already think that it's best practice te prefer relatively small modules anyway, and if you need a way to protect your private member variables from the module when the module isn't large, then you're definitely doing something wrong. Given the D philosophy that the module is the primary unit of encapsulation and that you should at least roughly understand the entire module when working on it (or it's almost certainly too large), having an access level to protect member variables from the rest of the module simply makes no sense. Anyone who feels the need for such an access level think about what they're doing with their code and why they feel the need for it - whether it's simply because they're used to it from other languages, or because they're organizing their code in a manner which is detrimental to maintainability. - Jonathan M Davis Here is the intial dip draft: https://github.com/12345swordy/DIPs/tree/Encapsulation If Walter Bright insist that the module is the unit of encapsulation then I propose we get rid of the "one module per file" restriction, by introducing sub modules. -Alex
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 10:26:14 UTC, Timon Gehr wrote: module borked; void atomicIncrement(int* p)@system{ import core.atomic; atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); } struct Atomic(T){ private T val; void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } void main()@safe{ Atomic!int i; auto a=&[i][0];// was: Atomic!int* a = import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++i.val; // race } --- Oh no! The author of the @trusted function (i.e. you) did not deliver on the promise they made! Now, before you go and tell me that I am stupid because I wrote bad code, consider the following: - It is perfectly @safe to access private members from the same module. Yes, so you need to place the @trusted code in a separate module. The @trusted code will be very rare (Atomic!T, lockfree queue, mutex, semaphore...). This will be in the standard library, possibly some other library. You should not be writing your own implementations of these. You should not be writing @trusted code without very good reason. You should be using @safe functions all over your code if at all possible. - You may not blame the my @safe main function for the problem. It is @safe, so it cannot be blamed for UB. Any UB is the result of a bad @trusted function, a compiler bug, or hardware failure. No, we blame the fact you have not blocked off non-thread-safe access to Atomic!T.val. What you have made is this: https://i.imgur.com/PnKMigl.jpg The piece of code to blame is the @trusted function - you can't trust it, since non-thread-safe access to Atomic!T.val has not been blocked off. As long as anyone can extend its interface, Atomic!T can't be thread-safe. I'll quote myself: For clarity: the interface of a type is any method, function, delegate or otherwise that may affect its internals. That means any free function in the same module, and any non-private members. I've actually missed some possibilities there - member functions of other types in the same module must also count as part of the interface. Because of this wide net, modules that implement thread-safe types with shared methods should be short and sweet. - The only @trusted function in this module was written by you. You said that there is a third implementation somewhere. If that one actually works, I apologize and ask you to please paste it again in this subthread. Here's the correct version: module atomic; void atomicIncrement(int* p) @system { import core.atomic; atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); } struct Atomic(T) { // Should probably mark this shared for extra safety, // but it's not strictly necessary private T val; void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } - module unborked; import atomic; void main() @safe { auto a = new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); //++i.val; // Cannot access private member } Once more, Joe Average Programmer should not be writing the @trusted code in Atomic!T.opUnary - he should be using libraries written by people who have studied the exact issues that make multithreading hard. -- Simen
Re: shared - i need it to be useful
On 22.10.18 14:39, Aliak wrote: On Monday, 22 October 2018 at 10:26:14 UTC, Timon Gehr wrote: --- module borked; void atomicIncrement(int* p)@system{ import core.atomic; atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); } struct Atomic(T){ private T val; void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } void main()@safe{ auto a=new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++a.val; // race } --- Oh no! The author of the @trusted function (i.e. you) did not deliver on the promise they made! hi, if you change the private val in Atomic to be “private shared T val”, is the situation the same? It's a bit different, because then there is no implicit unshared->shared conversion happening, and this discussion is only about that. However, without further restrictions, you can probably construct cases where a @safe function in one module escapes a private shared(T)* member to somewhere else that expects a different synchronization strategy. Therefore, even if we agree that unshared->shared conversion cannot be implicit in @safe code, the 'shared' design is not complete, but it would be a good first step to agree that this cannot happen, such that we can then move on to harder issues. E.g. probably it would be good to have something like @trusted data that cannot be manipulated from @safe code, such that @trusted functions can rely on some invariants.
Re: shared - i need it to be useful
On 22.10.18 12:26, Timon Gehr wrote: --- module borked; void atomicIncrement(int* p)@system{ import core.atomic; atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); } struct Atomic(T){ private T val; void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } void main()@safe{ Atomic!int i; auto a=&[i][0];// was: Atomic!int* a = import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++i.val; // race } --- Obviously, this should have been: --- module borked; void atomicIncrement(int*p)@system{ import core.atomic; atomicOp!"+="(*cast(shared(int)*)p,1); } struct Atomic(T){ private T val; void opUnary(string op:"++")()shared @trusted{ atomicIncrement(cast(T*)); } } void main()@safe{ auto a=new Atomic!int; import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++a.val; // race } --- (I was short on time and had to fix Manu's code because it was not actually compilable.)
Re: need help about get all public static function name
On Monday, 22 October 2018 at 12:32:57 UTC, test wrote: On Monday, 22 October 2018 at 12:16:50 UTC, Stanislav Blinov wrote: On Monday, 22 October 2018 at 12:03:22 UTC, test wrote: You're trying to call a static function 'getThis' on Fiber. The type 'Fiber' is really a Proxy!FiberS. Proxy doesn't have a static getThis() function. So the compiler tries an 'alias this', which forwards to a non-static member function getPayload(). To call that function, you need an instance of 'Proxy', which you don't have. I guess the first error message ("this for getPayload needs to be type Proxy not type TcpStream") just doesn't report that clearly. But this work: extern(C) void main(){ auto id = Fiber.getThis(); // work here } here also dont have Fiber instance. I think this is a bug. If I use "alias this " with a FiberS instance tuple memebr, it will work. but if I use alias this with @propery , it only work on static method, on delegate method it will use delegate this. This is kind like Javascript method this is come from caller place. I think it is a bug. please help me confirm this. If so please made a bug report for me.
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 10:26:14 UTC, Timon Gehr wrote: --- module borked; void atomicIncrement(int* p)@system{ import core.atomic; atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); } struct Atomic(T){ private T val; void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } void main()@safe{ Atomic!int i; auto a=&[i][0];// was: Atomic!int* a = import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++i.val; // race } --- Oh no! The author of the @trusted function (i.e. you) did not deliver on the promise they made! hi, if you change the private val in Atomic to be “private shared T val”, is the situation the same?
Re: need help about get all public static function name
On Monday, 22 October 2018 at 12:16:50 UTC, Stanislav Blinov wrote: On Monday, 22 October 2018 at 12:03:22 UTC, test wrote: You're trying to call a static function 'getThis' on Fiber. The type 'Fiber' is really a Proxy!FiberS. Proxy doesn't have a static getThis() function. So the compiler tries an 'alias this', which forwards to a non-static member function getPayload(). To call that function, you need an instance of 'Proxy', which you don't have. I guess the first error message ("this for getPayload needs to be type Proxy not type TcpStream") just doesn't report that clearly. But this work: extern(C) void main(){ auto id = Fiber.getThis(); // work here } here also dont have Fiber instance.
Re: need help about get all public static function name
On Monday, 22 October 2018 at 12:03:22 UTC, test wrote: On Monday, 22 October 2018 at 11:59:21 UTC, test wrote: On Monday, 22 October 2018 at 11:42:59 UTC, test wrote: I try made a simple example but it has no error: I find the way to show the error: https://run.dlang.io/is/f8cULz import std.traits; struct FiberS { static auto getThis(){ return Fiber.getId(); } } struct Proxy(T){ T* ptr; alias getPayload this; @property ref auto getPayload() inout return { return * ptr ; } static auto getId(){ return 1; } } alias Fiber = Proxy!(FiberS); extern(C) void main(){ auto id = Fiber.getThis(); // work here } struct TcpStream { void read(ubyte[] data){ auto id = Fiber.getThis(); // not work here in my case } } Let's analyze this call: auto id = Fiber.getThis(); You're trying to call a static function 'getThis' on Fiber. The type 'Fiber' is really a Proxy!FiberS. Proxy doesn't have a static getThis() function. So the compiler tries an 'alias this', which forwards to a non-static member function getPayload(). To call that function, you need an instance of 'Proxy', which you don't have. I guess the first error message ("this for getPayload needs to be type Proxy not type TcpStream") just doesn't report that clearly.
Re: need help about get all public static function name
On Monday, 22 October 2018 at 11:59:21 UTC, test wrote: On Monday, 22 October 2018 at 11:42:59 UTC, test wrote: I try made a simple example but it has no error: I find the way to show the error: https://run.dlang.io/is/f8cULz import std.traits; struct FiberS { static auto getThis(){ return Fiber.getId(); } } struct Proxy(T){ T* ptr; alias getPayload this; @property ref auto getPayload() inout return { return * ptr ; } static auto getId(){ return 1; } } alias Fiber = Proxy!(FiberS); extern(C) void main(){ auto id = Fiber.getThis(); // work here } struct TcpStream { void read(ubyte[] data){ auto id = Fiber.getThis(); // not work here in my case } }
Re: need help about get all public static function name
On Monday, 22 October 2018 at 11:42:59 UTC, test wrote: On Monday, 22 October 2018 at 11:18:20 UTC, Stanislav Blinov wrote: Error: template instance `TypeTemplate!(BaseType)` error instantiating I use alias this to allow call static method on proxyType. It work some time, but on other case it report: The code throw error is: struct TcpStream { void read(ubyte[] data){ auto id2 = Fiber.getThis(); // Error: this for getBoxPayload needs to be type BoxedTypeNode not type TcpStream } } If the read is static method, then there is no error. I can not fix this so I try use static method alias, but it work on normal case not my code (100KB+). I try made a simple example but it has no error:
Re: need help about get all public static function name
On Monday, 22 October 2018 at 11:42:59 UTC, test wrote: some how when I call "is(typeof(__traits(getMember, BaseType, name))) " in the template, my code report others error like: Error: no property fromPointer for type void Error: template instance TypeTemplate!(BaseType) is used as a type Error: template instance `TypeTemplate!(BaseType)` error instantiating That would be hard to diagnose without actually seeing the code, it seems there's something else going on.
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:22:19 UTC, Manu wrote: No no, they're repeated, not scattered, because I seem to have to keep repeating it over and over, because nobody is reading the text, or perhaps imaging there is a lot more text than there is. ... You mean like every post in opposition which disregards the rules and baselessly asserts it's a terrible idea? :/ ... I responded to your faulty program directly with the correct program, and you haven't acknowledged it. Did you see it? Right back at you. Quote: I think this is a typical sort of construction: struct ThreadsafeQueue(T) { void QueueItem(T*) shared; T* UnqueueItem() shared; } struct SpecialWorkList { struct Job { ... } void MakeJob(int x, float y, string z) shared // <- any thread may produce a job { Job* job = new Job; // <- this is thread-local PopulateJob(job, x, y, z); // <- preparation of a job might be complex, and worthy of the SpecialWorkList implementation jobList.QueueItem(job); // <- QueueItem encapsulates thread-safety, no need for blunt casts } void Flush() // <- not shared, thread-local consumer { Job* job; while (job = jobList.UnqueueItem()) // <- it's obviously safe for a thread-local to call UnqueueItem even though the implementation is threadsafe { // thread-local dispatch of work... // perhaps rendering, perhaps deferred destruction, perhaps deferred resource creation... whatever! } } void GetSpecialSystemState() // <- this has NOTHING to do with the threadsafe part of SpecialWorkList { return os.functionThatChecksSystemState(); } // there may be any number of utility functions that don't interact with jobList. private: void PopulateJob(ref Job job, ...) { // expensive function; not thread-safe, and doesn't have any interaction with threading. } ThreadsafeQueue!Job jobList; } This isn't an amazing example, but it's typical of a thing that's mostly thread-local, and only a small controlled part of it's functionality is thread-safe. The thread-local method Flush() also deals with thread-safety internally... because it flushes a thread-safe queue. All thread-safety concerns are composed by a utility object, so there's no need for locks, magic, or casts here. EndQuote; The above: 1) Will not compile, not currently, not under your proposal (presumably you forgot in frustration to cast before calling PopulateJob?..) 2) Does not in any way demonstrate a practical @safe application of an implicit conversion. As I wrote in the original response to that code, with that particular code it seems more like you just need forwarding methods that call `shared` methods under the hood (i.e. MakeJob), and it'd be "nice" if you didn't have to write those and could just call `shared` MakeJob on an un-`shared` reference directly. But these are all assumptions without seeing the actual usage. Please just stop acting like everyone here is opposing *you*. All you're doing is dismissing everyone with a "nuh-huh, you no understand, you bad". If it was just me, fine, it would mean I'm dumb and not worthy of this discussion. But this isn't the case, which means *you are not getting your point across*. And yet instead of trying to fix that, you're getting all snarky.
Re: need help about get all public static function name
On Monday, 22 October 2018 at 11:18:20 UTC, Stanislav Blinov wrote: On Monday, 22 October 2018 at 10:49:10 UTC, test wrote: note the added check that the member is not a type: is(typeof(__traits(getMember, BaseType, name))). You'll still need to iterate overloads if you want to get all static functions. Thanks for this. some how when I call "is(typeof(__traits(getMember, BaseType, name))) " in the template, my code report others error like: Error: no property fromPointer for type void Error: template instance TypeTemplate!(BaseType) is used as a type Error: template instance `TypeTemplate!(BaseType)` error instantiating
Re: Manu's `shared` vs the @trusted promise
On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote: The @trusted contract says that an @trusted function must be safe when called from an @safe function. That calling @safe function might be located in the same module, meaning it might have the same level of access as the @trusted function. That means, Atomic.incr is invalid. It's invalid whether Atomic.badboy exists or not. It's invalid because we can even possibly write an Atomic.badboy. That's my interpretation of the spec, at least. Frankly, this does not sound credible. According to this rationale, array access should be @system too, because it relies on the array not giving direct access to its length to the user, which would also in itself be @safe.
Re: need help about get all public static function name
On Monday, 22 October 2018 at 10:49:10 UTC, test wrote: test1.d = alias Fn1 = void function(); struct XX { alias Fn= Fn1; // ... } 'Fn' is not a static function, it's a type. I.e. you can declare a function pointer with it: Fn func; test2.d = import test1; void GetPub(BaseType)(){ // ... } My code works fine with your struct XX, with dmd 2.082. std.traits.hasMember expects an aggregate *type*, but you're trying to pass as instance. A revised GetPub: void GetPub(BaseType)(){ static foreach (name; __traits(allMembers, BaseType)) static if( name[0] !is '_' && is(typeof(__traits(getMember, BaseType, name))) && __traits(getProtection, __traits(getMember, BaseType, name)) == "public" ) { //static assert( hasMember!(BaseType.init, name)); static assert(hasMember!(BaseType, name)); static if( __traits(isStaticFunction, __traits(getMember, BaseType, name)) ) { pragma(msg, BaseType.stringof ~ "." ~ name); } } } note the added check that the member is not a type: is(typeof(__traits(getMember, BaseType, name))). You'll still need to iterate overloads if you want to get all static functions.
Re: need help about get all public static function name
On Monday, 22 October 2018 at 10:49:10 UTC, test wrote: On Monday, 22 October 2018 at 10:45:07 UTC, test wrote: On Monday, 22 October 2018 at 10:29:56 UTC, Stanislav Blinov wrote: extern(C) void main(){ GetPub!XX; } https://run.dlang.io/is/f295qE
Re: We need an internal keyword.
On Monday, October 22, 2018 2:30:21 AM MDT Basile B. via Digitalmars-d wrote: > On Monday, 22 October 2018 at 08:25:17 UTC, Andrea Fontana wrote: > > Moreover: you're the author of the module so you're supposed to > > know how it works and which members you should call or not. > > - team > - maintainer of a module written by someone that works elsewhere > now. > > that's two cases where strict privacy can be optionally a thing > avoiding wrong usage of private members within the scope of a > module. Part of the point is that if the module is large enough that the folks working on the code can't actually keep track of what's in it, then it's too large, and as such, if you need to protect your class or struct members from the rest of the module, then it really should be in a separate module for the code to be properly maintainable anyway. Yes, having multiple people involved makes the problem worse (especially when some of them join the team later), but it doesn't fundamentally change the issue. If it changes anything, it simply makes the argument stronger for preferring smaller modules so that they're easier to digest. Personally, I've found that larger modules have worked just fine for me without having to worry about these sort of encapsulation issues. It simply isn't a problem, and I don't recall ever seeing a bug because of it. But anyone who's worried about it always has the option of simply going for smaller modules, and the encapsulation problem is already solved without making the language any more complicated. Plenty of folks already think that it's best practice te prefer relatively small modules anyway, and if you need a way to protect your private member variables from the module when the module isn't large, then you're definitely doing something wrong. Given the D philosophy that the module is the primary unit of encapsulation and that you should at least roughly understand the entire module when working on it (or it's almost certainly too large), having an access level to protect member variables from the rest of the module simply makes no sense. Anyone who feels the need for such an access level think about what they're doing with their code and why they feel the need for it - whether it's simply because they're used to it from other languages, or because they're organizing their code in a manner which is detrimental to maintainability. - Jonathan M Davis
Re: Manu's `shared` vs the @trusted promise
On 22.10.18 11:40, Manu wrote: On Mon, Oct 22, 2018 at 2:21 AM ag0aep6g via Digitalmars-d wrote: [...] I don't agree. I prefer the stronger @trusted. As far as I know, the stronger one is the current one. The current one has the critical weakness that it causes **EVERY USER** to write unsafe code, manually casting things to shared. You're conflating @trusted with `shared`. As I've tried to show, your version of `shared` probably doesn't need the weaker @trusted. It can work with the stronger one. And I'm not trying to defend the current `shared` in any way. You're here spouting some fantasy With these snarky asides, you're making it difficult to argue for your side.
Re: need help about get all public static function name
On Monday, 22 October 2018 at 10:45:07 UTC, test wrote: On Monday, 22 October 2018 at 10:29:56 UTC, Stanislav Blinov wrote: On Monday, 22 October 2018 at 10:16:22 UTC, test wrote: and On Monday, 22 October 2018 at 10:45:07 UTC, test wrote: test1.d = alias Fn1 = void function(); struct XX { alias Fn= Fn1; enum Y { aa } static void Test(){} int id; } test2.d = import test1; void GetPub(BaseType)(){ static foreach (name; __traits(allMembers, BaseType)) static if( name[0] !is '_' && __traits(getProtection, __traits(getMember, BaseType, name)) == "public" ) { static assert( hasMember!(BaseType.init, name)); static if( __traits(isStaticFunction, __traits(getMember, BaseType, name)) ) { pragma(msg, typeof(BaseType.init).stringof ~ "." ~ name); } } } extern(C) void main(){ GetPub!XX; }
Re: need help about get all public static function name
On Monday, 22 October 2018 at 10:29:56 UTC, Stanislav Blinov wrote: On Monday, 22 October 2018 at 10:16:22 UTC, test wrote: I try use traits get all public static function of a struct pass to template... how to do this ? void allFunctions(T)() { import std.stdio; foreach (name; __traits(allMembers, T)) { static foreach (overload; __traits(getOverloads, T, name)) { static if (__traits(getProtection, overload) == "public" && __traits(isStaticFunction, overload)) { // 'overload' is an alias to a T's public static function writeln(name, ": ", typeof(overload).stringof); } } } } On the line: static foreach (overload; __traits(getOverloads, Type, name)) , throw error: is not accessible from module and
Re: Manu's `shared` vs the @trusted promise
On 22.10.18 11:33, Manu wrote: On Sun, Oct 21, 2018 at 3:05 PM ag0aep6g via Digitalmars-d wrote: [...] It's @trusted, not @safe... so I don't think you can say "It's invalid because we can even possibly write an Atomic.badboy" (I would agree to that statement if it were @safe). That's the thing about @trusted, you have to trust the engineer to confirm contextual correctness. Your definition of @trusted is weaker than mine. I think the one I gave is the one that's in the spec and the one that Walter and Timon work with. But semantics aside, how and why did you add code to this module? Do you usually add code to druntime or phobos? Assuming you did add code to this module, are you telling me that you don't understand what Atomic() does, and you also did not understand the rules of `shared`? You can't be trusted to write threadsafe code if you don't understand `shared`s rules. My point is, do you genuinely believe this is a high-risk? When did you last rewrite Atomic(T) because you didn't like the one in druntime? Have you ever heard of a case of that? I mean, I understand it's _possible_ to violate incr()'s promise, and that's why it's @trusted, and not @safe. But what's the probability of that happening by accident... and would you *honestly* make an argument that this unlikely scenario is more likely to occur than any of your 900 high-level engineers making any sort of mistake with respect to the *use* of shared's current rules, which require unsafe interaction at every call, by every end-user? Most users don't modify druntime.[...] I agree the situation you fear is technically possible, but I think it's very unlikely, You're arguing with probability while the other camp is entrenched in fundamentals. The goal is a very strong @safe. All @safe code must be compiler-verifiable safe. With the weaker @trusted, that doesn't hold when the @safe code is next to @trusted code. So the weaker @trusted is unacceptable. By the way, can you dial down the confrontational rhetoric, please? I'm pretty much trying to help get your point across here. I don't need snarky questions/remarks about my ability to write thread-safe code. Even if I can't write correct code, it's besides the point. and in balance to the risks associated with shared today, which is completely unsafe at the user-facing level, and also completely unregulated (you can access members freely)... I think most agree it's bad that `shared` data can currently be accessed freely without casting, without atomics, without synchronization. I know that I agree. [...] I've said on at least 5 other occasions, I'm sure there are a whole lot of options we can explore to assist and improve the probability that the ground-level author doesn't make a mistake (although I am quite confident you'd be wasting your time, because they won't make a mistake like this anyway). That conversation has nothing to do with the validity of the rules though, which is what the other 400 post thread is about. The perception is that one has to break the (stronger) @trusted promise in order to do anything with your version of `shared`. And that's perceived as bad. So you have to show that breaking the @trusted promise is not necessary. I've tried to show that. Or you have to show that a weaker @trusted is preferable to the stronger one. Convincing people of that would be a hard task, I think. If you *do* trust the 5-10 @trusted functions in the library; Is my scheme sound? If you can implement them without breaking the (strong) @trusted promise, then I guess so. If you can't, then no (arguably, depending on how @trusted is defined). [...] We can fuss about the details until the cows come home, but I'm finding it impossible to get everyone on the same page in the first place. I think we're making progress right here. It seems to me that there are two slightly different definitions of @trusted floating around. Ideally, everyone would agree which one is correct (or more useful). Things might fall into place then.
Re: Manu's `shared` vs the @trusted promise
On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote: It took me a while to understand Manu's idea for `shared`, and I suspect that it was/is the same for others... Three threads one... Three threads two... Three threads three! Sold! Thank you very much, ladies and gentlemen!
Re: need help about get all public static function name
On Monday, 22 October 2018 at 10:16:22 UTC, test wrote: I try use traits get all public static function of a struct pass to template... how to do this ? void allFunctions(T)() { import std.stdio; foreach (name; __traits(allMembers, T)) { static foreach (overload; __traits(getOverloads, T, name)) { static if (__traits(getProtection, overload) == "public" && __traits(isStaticFunction, overload)) { // 'overload' is an alias to a T's public static function writeln(name, ": ", typeof(overload).stringof); } } } }
Re: shared - i need it to be useful
On 22.10.18 02:54, Manu wrote: On Sun, Oct 21, 2018 at 5:40 PM Timon Gehr via Digitalmars-d wrote: On 21.10.18 21:04, Manu wrote: On Sun, Oct 21, 2018 at 12:00 PM Timon Gehr via Digitalmars-d wrote: On 21.10.18 17:54, Nicholas Wilson wrote: As soon as that is done, you've got a data race with the other existing unshared aliases. You're in @trusted code, that is the whole point. The onus is on the programmer to make that correct, same with regular @safe/@trusted@system code. Not all of the parties that participate in the data race are in @trusted code. The point of @trusted is modularity: you manually check @trusted code according to some set of restrictions and then you are sure that there is no memory corruption. Note that you are not allowed to look at any of the @safe code while checking your @trusted code. You will only see an opaque interface to the @safe code that you call and all you know is that all the @safe code type checks according to @safe rules. Note that there might be an arbitrary number of @safe functions and methods that you do not see. Think about it this way: you first write all the @trusted and @system code, and some evil guy who does not like you comes in after you looks at your code and writes all the @safe code. If there is any memory corruption, it will be your fault and you will face harsh consequences. Now, design the @safe type checking rules. It won't be MP! Note that there may well be a good way to get the good properties of MP without breaking the type system, but MP itself is not good because it breaks @safe. Show me. Nobody has been able to show that yet. I'd really like to know this. I just did, There's no code there... just a presumption that the person who wrote the @trusted code did not deliver the promise they made. ... Yes, because there is no way to write @trusted code that holds its promise while actually doing something interesting in multiple threads if @safe code can implicitly convert from unshared to shared. but if you really need to, give me a non-trivial piece of> correct multithreaded code that accesses some declared-unshared field from a shared method and I will show you how the evil guy would modify some @safe code in it and introduce race conditions. It needs to be your code, as otherwise you will just claim again that it is me who wrote bad @trusted code. You can pick on any of my prior code fragments. They've all been ignored so far. I don't want "code fragments". Show me the real code. I manually browsed through posts now (thanks a lot) and found this implementation: struct Atomic(T){ void opUnary(string op : "++")() shared { atomicIncrement(); } private T val; } This is @system code. There is no @safe or @trusted here, so I am ignoring it. Then I browsed some more, because I had nothing better to do, and I found this. I completed it so that it is actually compilable, except for the unsafe implicit conversion. Please read this code, and then carefully read the comments below it before you respond. I will totally ignore any of your answers that arrive in the next two hours. --- module borked; void atomicIncrement(int* p)@system{ import core.atomic; atomicOp!("+=",int,int)(*cast(shared(int)*)p,1); } struct Atomic(T){ private T val; void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } void main()@safe{ Atomic!int i; auto a=&[i][0];// was: Atomic!int* a = import std.concurrency; spawn((shared(Atomic!int)* a){ ++*a; }, a); ++i.val; // race } --- Oh no! The author of the @trusted function (i.e. you) did not deliver on the promise they made! Now, before you go and tell me that I am stupid because I wrote bad code, consider the following: - It is perfectly @safe to access private members from the same module. - You may not blame the my @safe main function for the problem. It is @safe, so it cannot be blamed for UB. Any UB is the result of a bad @trusted function, a compiler bug, or hardware failure. - The only @trusted function in this module was written by you. You said that there is a third implementation somewhere. If that one actually works, I apologize and ask you to please paste it again in this subthread.
need help about get all public static function name
I try use traits get all public static function of a struct pass to template. Compiler report " .Function is not accessible from module " with __traits(isStaticFunction, __traits(getMember, Type , name)). If I add " __traits(getProtection, __traits(getMember, Type, name)) == "public" before "__traits(isStaticFunction, __traits(getMember, Type , name))", it report " argument void function(void*) nothrow @nogc has no protection". If I add "isFunction!(typeof(__traits(getMember, Type, name)))" before all this, It report type State is not an expression. If I use "isFunction!(__traits(getMember, BaseType, name)) ", it report again "argument void function(void*) nothrow @nogc has no protection" how to do this ?
Re: D Binding to GUI libraries
On Mon, 2018-10-22 at 03:49 -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote: > […] > Just to see what's up with this "Qt-based Ubuntu", which to me, is > much > like hearing of Mario on a Dreamcast, or Sonic on SNES... Canonical got heavily into Qt (well QML actually) when they were going to do a mobile phone. Lots of Go code. All dropped when the phone got dropped. Ubuntu is basically Debian with some proprietary stuff. So for a (usually, caveat freezes) more rolling release Debian Sid is fine. GNOME is the default but you can easily change to other GTK+ based UIs or the full KDE and Qt thing. I am guess Arch has a play in this game of rolling releases with GNOME or KDE. Fedora Rawhide like Debian Sid defaults to GNOME, but allows for a switch to KDE. However Fedora Rawhide is, like Debian Sid, only sort of a rolling release. -- Russel. === Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Roadm: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk signature.asc Description: This is a digitally signed message part
Re: D Binding to GUI libraries
Jacob, GitHub is currently making a total mess for me of our conversation on Issue 42, I see stuff then it goes away. Apologies if I have made a mess of that conversation for you. On Sun, 2018-10-21 at 20:24 +0200, Jacob Carlborg via Digitalmars-d wrote: > […] > There's probably a ton of business/enterprise applications that are > written in Java. Masses, but most Java is Web backend. JetBrains and Eclipse are the bastions of desktop Java applications. > But I don't care for that, that's why I'm using D :) I don't blame you. Whilst I like D, I fear I am being pulled more and more to Rust for GUI stuff. > Not sure what you mean with "ship" here. Swing and JavaFX are > shipped > with Java. Swing is, but JavaFX is now OpenJFX and a separate think to OpenJDK. > Eclipse itself is built using SWT. Indeed. But compared to Qt (and maybe GTK+ and wxWidgets) it is very much a niche framework. […] > > Linux doesn't have a "native" GUI in the same sense as macOS and > Windows. Or it has many native GUIs whereas Windows and macOS offer no choice? > […] > > Qt is not native, at least not on macOS. Are any of the Qt D > bindings > actually useful? wxD seems very old, D1 old, is that useable? I had thought Qt for Mac did indeed map down to the Cocoa layer. I fear qtD and dqt are not up to the task. I do not know about dqml. I have been told QtE5 is workable. wxD would need some serious work in that case. > When I said that DWT is basically the only native D toolkit, I failed > to > also include: up to date (as in working with the latest compiler), > working and cross-platform. :-) I still think getting a Qt binding for D à la PyQt, PySide2, Rust-Qt, i.e. automated with minimal manual tweeks, would be a Very Good Thing™ for the D pitch in the desktop GUI applications arena. -- Russel. === Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Roadm: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk signature.asc Description: This is a digitally signed message part
Re: shared - i need it to be useful
On Mon, Oct 22, 2018 at 2:30 AM Walter Bright via Digitalmars-d wrote: > > On 10/22/2018 1:34 AM, Manu wrote: > > I posted it, twice... 2 messages, back to back, and you're responding > > to this one, and not that one. I'll post it again... > > > Posting it over and over is illustrative of the failure of posting proposal > documents to the n.g. instead of posting it as a DIP which can be referred to: > > 1. nobody knows which of your 70 messages are the ones with the proposal in it > > 2. with multiple posts of the proposal, nobody knows which one is the most > up-to-date one It hasn't changed. Not one single bit. I haven't changed a single detail in this thread. > Doing it this way does not work. Continuing to repost it is a waste of your > time. Post it as a DIP and link to it. And you STILL ignored my post >_< Please look at the proper code that implements your broken example. I know you've seen it now.
Re: Manu's `shared` vs the @trusted promise
On Mon, Oct 22, 2018 at 2:21 AM ag0aep6g via Digitalmars-d wrote: > > On 22.10.18 10:39, Simen Kjærås wrote: > > On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote: > [...] > > It's invalid only if Atomic.badboy exists. > > I don't agree. I prefer the stronger @trusted. As far as I know, the > stronger one is the current one. The current one has the critical weakness that it causes **EVERY USER** to write unsafe code, manually casting things to shared. You're here spouting some fantasy about a bad-actor hacking cruft into Atomic() in druntime... Like, if you're worried about the author of Atomic(T), how about _every user, including the interns_? author:users is a 1:many relationship. I can't imagine any line of reason that doesn't find it logical that the proper placement of the burden of correctly handling @trusted code should be the one expert threadsafe library author, and not *every user ever*, because that's what the current model prescribes, and the entire point for wasting my breath.
Re: shared - i need it to be useful
On 22/10/2018 10:28 PM, Walter Bright wrote: On 10/22/2018 1:34 AM, Manu wrote: I posted it, twice... 2 messages, back to back, and you're responding to this one, and not that one. I'll post it again... Posting it over and over is illustrative of the failure of posting proposal documents to the n.g. instead of posting it as a DIP which can be referred to: 1. nobody knows which of your 70 messages are the ones with the proposal in it 2. with multiple posts of the proposal, nobody knows which one is the most up-to-date one Doing it this way does not work. Continuing to repost it is a waste of your time. Post it as a DIP and link to it. As I've said previously, it doesn't need to be a good DIP or anywhere near complete. It just needs code examples comparing current and proposed behavior with some text about semantics changes.
Re: Manu's `shared` vs the @trusted promise
On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote: With Manu's `shared`, there is implicit conversion from non-`shared` to `shared`. It would essentially become a language rule. For that rule to be sound, any access to `shared` data must be @system. And more challengingly, @system/@trusted code must be written carefully with the new rule in mind. Well, we have __gshared for that. When code is written carefully, it works fine, C, C# and Java do well that way, you just architecturally minimize amount of multithreaded code, and it becomes manageable, for an example see https://github.com/dlang/druntime/blob/master/src/core/sync/semaphore.d
Re: Manu's `shared` vs the @trusted promise
On Sun, Oct 21, 2018 at 3:05 PM ag0aep6g via Digitalmars-d wrote: > > It took me a while to understand Manu's idea for `shared`, and I suspect > that it was/is the same for others. At the same time, Manu seems > bewildered about the objections. I'm going to try and summarize the > situation. Maybe it can help advance the discussion. > > > (1) How Does Manu's `shared` Interact with @trusted? > > With Manu's `shared`, there is implicit conversion from non-`shared` to > `shared`. It would essentially become a language rule. For that rule to > be sound, any access to `shared` data must be @system. And more > challengingly, @system/@trusted code must be written carefully with the > new rule in mind. Well, just to be clear, I wouldn't say "access to shared data is @system", I'd say, "there is no access to shared data". The only way to access data members from a shared instance is to cast away shared; and naturally, that is @system. So if this is what you mean, then I agree. > (Manu, you might say that the conversion follows from `shared` methods > being "guaranteed threadsafe", but I think it's easier to reason this > way. Anyway, potayto potahto.) > > The consequence is: In @trusted code, I have to make sure that I have > exclusive access to any `shared` data that I use. This isn't strictly true, other access are possible, as long as they're atomic and you encapsulate properly, but I'll go with you here... > If code that is not > under my control can obtain a non-`shared` view of the same data, I have > failed and my @trusted code is invalid. Right. > An example in code (just rehashing code given by Manu): > > > struct Atomic > { > private int x; > > void incr() shared @trusted > { > /* ... atomically increment x ... */ atomicIncrement(cast(int)*); // <- I added the unsafe call to atomicInc for clarity > } > > /* If this next method is here, the one above is invalid. It's the > responsibility of the author of the @trusted code to make sure > that this doesn't happen. */ > > void badboy() @safe { ++x; } /* NO! BAD! NOT ALLOWED! */ > } > Right, this is the rule that I depend on. It carries the weight of the model. Fortunately, the number of tools of this sort are very few in number, and you probably would never write any of them yourself. > (2) What's Wrong with That? > > The @trusted contract says that an @trusted function must be safe when > called from an @safe function. That calling @safe function might be > located in the same module, meaning it might have the same level of > access as the @trusted function. > > That means, Atomic.incr is invalid. It's invalid whether Atomic.badboy > exists or not. It's invalid because we can even possibly write an > Atomic.badboy. That's my interpretation of the spec, at least. It's @trusted, not @safe... so I don't think you can say "It's invalid because we can even possibly write an Atomic.badboy" (I would agree to that statement if it were @safe). That's the thing about @trusted, you have to trust the engineer to confirm contextual correctness. But semantics aside, how and why did you add code to this module? Do you usually add code to druntime or phobos? Assuming you did add code to this module, are you telling me that you don't understand what Atomic() does, and you also did not understand the rules of `shared`? You can't be trusted to write threadsafe code if you don't understand `shared`s rules. My point is, do you genuinely believe this is a high-risk? When did you last rewrite Atomic(T) because you didn't like the one in druntime? Have you ever heard of a case of that? I mean, I understand it's _possible_ to violate incr()'s promise, and that's why it's @trusted, and not @safe. But what's the probability of that happening by accident... and would you *honestly* make an argument that this unlikely scenario is more likely to occur than any of your 900 high-level engineers making any sort of mistake with respect to the *use* of shared's current rules, which require unsafe interaction at every call, by every end-user? Most users don't modify druntime. I think people are drastically over-estimating how much such @trusted code would exist. Everybody fears multithreading, and nobody wants to write data-races. If you lived in a world where we had a model to describe @safe multithreading, you would do everything you can to stay inside that playground, and engaging in unsafe threading code would quickly become a pungent stench. I suspect you only think about writing @trusted code so much because that's what the existing implementation of `shared` has trained us all to do. > But according to Manu, Atomic.incr is fine as long as there's no > Atomic.badbody that messes things up. So it looks like we're expected to > violate the @trusted contract when dealing with Manu's `shared`. But > when we routinely have to break the rules, then that's a sign that the > rules are bad. I lost you here...
Re: shared - i need it to be useful
On 10/22/2018 1:34 AM, Manu wrote: I posted it, twice... 2 messages, back to back, and you're responding to this one, and not that one. I'll post it again... Posting it over and over is illustrative of the failure of posting proposal documents to the n.g. instead of posting it as a DIP which can be referred to: 1. nobody knows which of your 70 messages are the ones with the proposal in it 2. with multiple posts of the proposal, nobody knows which one is the most up-to-date one Doing it this way does not work. Continuing to repost it is a waste of your time. Post it as a DIP and link to it.
Re: Manu's `shared` vs the @trusted promise
On 22.10.18 10:39, Simen Kjærås wrote: On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote: [...] It's invalid only if Atomic.badboy exists. I don't agree. I prefer the stronger @trusted. As far as I know, the stronger one is the current one. Essentially, since the module is the unit of encapsulation, it also needs to be the unit of programmer responsibility. [...] struct Atomic { shared/*!*/ int x; void incr() shared @trusted { /* ... */ } /* Now this gets rejected by the compiler: */ void badboy() @safe { ++x; } /* compiler error */ } With a `shared int x` there's no way that @safe code might access it, so the @trusted promise is kept. It's clearly better to mark x as shared, yes. However, I fail to see how this is significantly different from the above - J. Random Newbie can still open that file, remove the 'shared' qualifier on x, and rewrite badboy to be thread-unsafe. If we're going to assume that bad actors have write-access to all files, there's no end to the trouble that can be had. It's not about bad actors, it's about mistakes and finding them. Of course, you can still makes mistakes with the stronger @trusted, but they will be in @trusted code. In the example, if anything's wrong you know that the mistake must be in `incr`, because it's the only @trusted function. You don't even have to look at the @safe code. The compiler can check that it's ok.
Re: shared - i need it to be useful
On 10/22/2018 1:42 AM, Manu wrote: You removed whatever comment you're referring to. If your newsreader cannot find the antecedent, you badly need to use a better one. Thunderbird handles this rather well, there's no reason to use an inferior one. Or just click the <- button: https://digitalmars.com/d/archives/digitalmars/D/shared_-_i_need_it_to_be_useful_320165.html#N320607 I don't understand any of Timon's posts in this thread at all, which is unusual because he's usually pretty clear. I suspect Timon is equally frustrated at not getting his point across.
[Issue 18290] std.conv.parse throws ConvOverflowException for negative values in hex
https://issues.dlang.org/show_bug.cgi?id=18290 --- Comment #2 from Răzvan Ștefănescu --- (In reply to Tiberiu Lepadatu from comment #1) > (In reply to Răzvan Ștefănescu from comment #0) > > string input = "8000"; > > auto x = parse!int(input, 16); > > //ConvOverflowException > > I feel that this is not a bug. To show that you > are using a hex string you must use "0x" in front. > If you write "0x8000" instead of "8000" > there is no bug. parsing 0x8000 will read only the "0" before x, which is not the intended behavior, therefore x will become 0, not -2147483648. In order to show that I am using a hex string, I specify the radix (16). To go further, how do I parse a string with radix 7? How do I prefix the string? --
Re: shared - i need it to be useful
On Mon, Oct 22, 2018 at 12:55 AM Walter Bright via Digitalmars-d wrote: > > On 10/21/2018 11:58 AM, Timon Gehr wrote: > > [...] > > Thank you, Timon, for a nice explanation of what I was trying to express. You removed whatever comment you're referring to. I don't understand any of Timon's posts in this thread at all, which is unusual because he's usually pretty clear.
Re: Manu's `shared` vs the @trusted promise
On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote: (2) What's Wrong with That? The @trusted contract says that an @trusted function must be safe when called from an @safe function. That calling @safe function might be located in the same module, meaning it might have the same level of access as the @trusted function. That means, Atomic.incr is invalid. It's invalid whether Atomic.badboy exists or not. It's invalid because we can even possibly write an Atomic.badboy. That's my interpretation of the spec, at least. But according to Manu, Atomic.incr is fine as long as there's no Atomic.badbody that messes things up. So it looks like we're expected to violate the @trusted contract when dealing with Manu's `shared`. But when we routinely have to break the rules, then that's a sign that the rules are bad. It's invalid only if Atomic.badboy exists. As the writer of Atomic, you should not put badboy in there. If someone else on your dev team put it there, you have bigger problems - do more code reviews, put stuff in smaller modules, etc. Essentially, since the module is the unit of encapsulation, it also needs to be the unit of programmer responsibility. (3) Maybe It Can Be Made to Work? There might be a way to implement Atomic without breaking the @trusted promise: struct Atomic { shared/*!*/ int x; void incr() shared @trusted { /* ... */ } /* Now this gets rejected by the compiler: */ void badboy() @safe { ++x; } /* compiler error */ } With a `shared int x` there's no way that @safe code might access it, so the @trusted promise is kept. It's clearly better to mark x as shared, yes. However, I fail to see how this is significantly different from the above - J. Random Newbie can still open that file, remove the 'shared' qualifier on x, and rewrite badboy to be thread-unsafe. If we're going to assume that bad actors have write-access to all files, there's no end to the trouble that can be had. -- Simen
Re: shared - i need it to be useful
Third time's the charm maybe? - repeated, 3rd time On Sun., 21 Oct. 2018, 2:55 am Walter Bright via Digitalmars-d, wrote: > > On 10/20/2018 11:24 AM, Manu wrote: > > This is an unfair dismissal. > > It has nothing at all to do with fairness. It is about what the type system > guarantees in @safe code. To repeat, the current type system guarantees in > @safe > code that T* and shared(T)* do not point to the same memory location. > > Does your proposal maintain that or not? It's a binary question. By the definition Nick pulled from Wikipedia and posted for you a few posts back, yes, my proposal satisfies Wikipedia's definition of no aliasing. I understand that property is critical, and I have carefully designed for it. > > I'm not sure you've understood the proposal. > > This is the reason for the implicit conversion. It provides safe > > transition. > > I don't see any way to make an implicit T* to shared(T)* safe, or vice versa. > The T* code can create more aliases that the conversion doesn't know about, > and > the shared(T)* code can hand out aliases to other threads. So it all falls to > pieces. T* can't make additional T* aliases on other threads; there can only be one thread with T*. shared(T)* can not make a T*. shared(T)* has no read or write access, so it's not an alias of T* by Wikipedia's definition. Only threadsafe functions can do anything to T. The leap of faith is; some @trusted utility functions at the bottom of the shared stack makes a promise that it is threadsafe, and must deliver that promise. I don't think this is unreasonable; this is the nature of @trusted functions, they make a promise, and they must keep it. If the trusted function does not lie, then the chain of trust holds upwards through the stack. The are very few such trusted functions in practise. Like, similar to the number of digits you have. > Using a 'scope' qualifier won't work, because 'scope' isn't transitive, > while shared is, i.e. U** and shared(U*)*. I don't think I depend on scope in any way. That was an earlier revision of thinking in an older thread. > > I'm not sure how to clarify it, what can I give you? > > Write a piece of code that does such an implicit conversion that you argue is > @safe. Make the code as small as possible. Your example: > > > int* a; > > shared(int)* b = a; > > This is not safe. > > Manu's Proposal --- > @safe: > int i; > int* a = > StartNewThread(a); // Compiles! Coder has no idea! > > ... in the new thread ... > void StartOfNewThread(shared(int)* b) { > > ... we have two threads accessing 'i', > one thinks it is shared, the other unshared, > and StartOfNewThread() has no idea and anyone > writing code for StartOfNewThread() has no way > to know anything is wrong ... > > lockedIncrement(b); // Data Race! > } This program doesn't compile. You receive an error because it is not safe. The function is `lockedIncrement(int*)`. It can't receive a shared argument; the function is not threadsafe by my definition. You have written a program that produces the expected error that alerts you that you have tried to do un-@safe and make a race. Stanislav produced this same program, and I responded with the correct program a few posts back. I'll repeat it here; the @safe program to model this interaction is: @safe: // function is NOT threadsafe by my definition, can not be called on shared arguments void atomicIncrement(int*); struct Atomic(T) { // encapsulare the unsafe data so it's inaccessible by any unsafe means private T val; // perform the unsafe cast in a trusted function // we are able to assure a valid calling context by encapsulating the data above void opUnary(string op : "++")() shared @trusted { atomicIncrement(cast(T*)); } } Atomic!int i; Atomic!int* a = StartNewThread(a); // Compiles, of course! ++i; // no race ... in the new thread ... void StartOfNewThread(shared(Atomic!int)* b) { //... we have two threads accessing 'i', one has thread-local access, this one has a restricted shared access. // here, we have a shared instance, so we can only access `b` via threadsafe functions. // as such, we can manipulate `b` without fear. ++i; // no race! } > Your proposal means that the person writing the lockedIncrement(), which is a > perfectly reasonable thing to do, simply cannot write it in a way that has a > @safe interface Correct, the rules of my proposal apply to lockedIncrement(). They apply to `shared` generally. lockedIncrement() is not a threadsafe function. You can't call it on a shared instance, because `int`s API (ie, all intrinsic operations) are not threadsafe. lockedIncrement() can't promise threadsafe access to `shared(int)*`, so the argument is not shared. Your program made the correct compile error about doing unsafety, but the location of the compile error is different under my proposal; complexity is worn by the shared library author, rather
Re: shared - i need it to be useful
On Mon, Oct 22, 2018 at 12:50 AM Walter Bright via Digitalmars-d wrote: > > On 10/21/2018 5:54 PM, Manu wrote: > > Would you please respond to my messages, and specifically, respond to > > the code that I presented to you in response to your broken example. > > Or any of my earlier fragments throughout this thread. I've shared > > quite a few, and so far, nobody has ever produced a criticism of any > > of my fragments. They've just been skipped over. > > That's just the problem. You've posted 62 messages so far in this thread, and > then there's all the ones Nicholas posted. I sent it twice... again just a short while ago right before this one... but you responded to this one and not that one O_o > Trying to assemble the "earlier fragments throughout this thread" is not > practical for readers, and the endless nature of this thread is ample evidence > for it. The n.g. is a place to discuss a proposal, not the proposal itself. > > This change is definitely merits an actual proposal DIP, so that one is > assured > of seeing the complete proposal, rationale, examples, etc., in one document, > as > well as not being distracted by sidebars, thread drift, and mistakes. This > document can evolve with corrections and clarifications from the discussion, > and > anyone can get up to speed quickly by just reading the latest version of it. Okay, but I still want you to respond to my corrections of your program, which were in direct response to you... twice. > > But the one aimed directly at your own most recent sample program > > addresses your program directly. > > My most recent sample program was a direct criticism of one of your fragments, > so please don't say "nobody has ever ...". I do understand your frustration at > finding it hard to get your point across, but the problem at least for me is > trying to mine it from nuggets scattered across 62 posts. Mine it, refine it, > cast it into an ingot, then present it as a DIP. I posted it, twice... 2 messages, back to back, and you're responding to this one, and not that one. I'll post it again...
Re: We need an internal keyword.
On Monday, 22 October 2018 at 08:25:17 UTC, Andrea Fontana wrote: Moreover: you're the author of the module so you're supposed to know how it works and which members you should call or not. - team - maintainer of a module written by someone that works elsewhere now. that's two cases where strict privacy can be optionally a thing avoiding wrong usage of private members within the scope of a module.
Re: We need an internal keyword.
On Sunday, 21 October 2018 at 03:17:23 UTC, 12345swordy wrote: So that classes can share some of their variables but not others in a module. IE. class A { internal int A; //This is shared in the module private int B; // But not this. } No need to reintroduce the "Friend" feature from cpp. As just said by others, if you need it probably your module is too big and you have to split. Moreover: you're the author of the module so you're supposed to know how it works and which members you should call or not. Anyway since they're private you can name them in particular way to remember yourself not to use them eg: int internal_A; Andrea
Re: We need an internal keyword.
On Sunday, 21 October 2018 at 23:50:57 UTC, 12345swordy wrote: If the cost out way the benefits then I simply introduce the "strict" keyword to avoid code breakage, or introduce the optional module scoping. -Alex Looking at the dlang.org page about visibility attributes, the `package` keyword can have an argument specifying which package has access to the symbol. What if `private` could have an argument dictating which other symbol could have access to that private symbol ? Setting this argument to the private symbol's own class would effectively make it strictly private. This wouldn't require a new keyword, and that syntax is not valid D code so it wouldn't break any existing code. Though it would look a bit weird, and it would also basically introduce a sort of "friend" feature. I don't know, that was just a random thought that crossed my mind just now.
Re: shared - i need it to be useful
On 10/21/2018 11:58 AM, Timon Gehr wrote: [...] Thank you, Timon, for a nice explanation of what I was trying to express.
Re: D Binding to GUI libraries
On 10/22/18 1:58 AM, Neia Neutuladh wrote: Unity 7 and prior for the desktop use Nux, an OpenGL-based widget toolkit. Unity 8 and all mobile versions of Unity use Qt. The application set that Ubuntu shipped with Unity was, I think, heavier on the GTK+ side. Fascinating. I'm actually shocked by this, TBH. I used to be an Ubuntu user, from back BEFORE Unity, back when Ubuntu used GNOME 2. My observation and experience had always been that both Ubuntu and Gnome 2 were trying to be an open-source imitation of OSX. Then, Gnome moved to v3 (and completely lost its mind) and Ubuntu responded by switching to its own brand-new still-GTK-based Unity. But that made Ubuntu feel all the *more* like an OSS OSX-clone, prompting me to migrate upstream to Debian, and eventually to Manjaro. Meanwhile, I observed Canonical lead Kubuntu to become nothing but more, and more, and more obscure and marginalized. And then there was the news of Canonical starting into desktop spyware territory, and by then I was already long gone... So I'm honestly *shocked* to hear this. I NEVER would've guessed. I'm pretty sold on rolling-release at this point, but I'm intrigued enough that I'm gonna have to give the latest Ubuntu a try, at least in a VM. Just to see what's up with this "Qt-based Ubuntu", which to me, is much like hearing of Mario on a Dreamcast, or Sonic on SNES...
Re: shared - i need it to be useful
On 10/21/2018 5:54 PM, Manu wrote: Would you please respond to my messages, and specifically, respond to the code that I presented to you in response to your broken example. Or any of my earlier fragments throughout this thread. I've shared quite a few, and so far, nobody has ever produced a criticism of any of my fragments. They've just been skipped over. That's just the problem. You've posted 62 messages so far in this thread, and then there's all the ones Nicholas posted. Trying to assemble the "earlier fragments throughout this thread" is not practical for readers, and the endless nature of this thread is ample evidence for it. The n.g. is a place to discuss a proposal, not the proposal itself. This change is definitely merits an actual proposal DIP, so that one is assured of seeing the complete proposal, rationale, examples, etc., in one document, as well as not being distracted by sidebars, thread drift, and mistakes. This document can evolve with corrections and clarifications from the discussion, and anyone can get up to speed quickly by just reading the latest version of it. > But the one aimed directly at your own most recent sample program > addresses your program directly. My most recent sample program was a direct criticism of one of your fragments, so please don't say "nobody has ever ...". I do understand your frustration at finding it hard to get your point across, but the problem at least for me is trying to mine it from nuggets scattered across 62 posts. Mine it, refine it, cast it into an ingot, then present it as a DIP.
Re: We need an internal keyword.
On Sunday, 21 October 2018 at 23:50:57 UTC, 12345swordy wrote: On Sunday, 21 October 2018 at 21:48:22 UTC, Laurent Tréguier wrote: On Sunday, 21 October 2018 at 17:09:05 UTC, 12345swordy wrote: [...] It's not "my" solution. It's D's solution. I perfectly understand why you'd want this and I would probably make use of a private/internal difference myself if it was available. If you already know about this solution however, I don't even know why you're starting this thread; since changing the behavior of private would be a major language change breaking tons of existing codebases, plus it would require adding yet another keyword. Given that this conversation has happened before and things haven't changed, I'm very doubtful that it could happen at any point in time, sadly. If the cost out way the benefits then I simply introduce the "strict" keyword to avoid code breakage, or introduce the optional module scoping. -Alex Technically, introducing any new keyword is also a potentially code breaking change. Any symbol named "strict" would have to be changed. This is why I'm doubtful that such a change would be accepted.
Re: Wed Oct 17 - Avoiding Code Smells by Walter Bright
On Friday, 19 October 2018 at 03:53:12 UTC, Walter Bright wrote: On 10/15/2018 2:23 PM, Walter Bright wrote: I'm giving a presentation at: http://nwcpp.org/ See you there! Had a nice crowd there last night. Apparently lots of people were interested in this topic! Video: https://www.youtube.com/watch?v=lbp6vwdnE0k=youtu.be Slides: http://nwcpp.org/talks/2018/code_smells.pdf https://www.reddit.com/r/programming/comments/9qbhw2/nwcpp_walter_bright_talks_about_the_code_smells/
[Issue 4957] std.concurrency does not allow to pass Tid in struct fields
https://issues.dlang.org/show_bug.cgi?id=4957 Mathias LANG changed: What|Removed |Added CC||pro.mathias.l...@gmail.com --- Comment #5 from Mathias LANG --- New attempt: https://github.com/dlang/phobos/pull/6738 --
Re: D Binding to GUI libraries
On 10/22/18 1:08 AM, Gerald wrote: On Monday, 22 October 2018 at 04:41:08 UTC, Nick Sabalausky (Abscissa) wrote: On 10/21/18 1:13 PM, Russel Winder wrote: [...] First of all, minor nitpick: Unless some bombshell news occurred that I managed to miss, Ubuntu pushes their own Unity, NOT Gnome. Yes, that's still GTK, but still...accuracy...FWIW. To be accurate, Ubuntu announced the dropping of Unity back in April 2017. Current versions of Ubuntu use Gnome. https://phoronix.com/scan.php?page=news_item=Ubuntu-Dropping-Unity Wow! I really am out of the loop then. That is SERIOUSLY *MEGATON*-level announcement. I'm shocked that I missed it. I would never have even guessed. Thanks for the input! Chalk me up as one who prefers Gnome over KDE. I like the clean UI that gnome provides and the adherence to a common HIG. KDE is way too fussy and busy for my taste. I also don't agree this is a minority viewpoint. Like Russell though I'm glad there is choice and people can use what they prefer be it Gnome, KDE, Mate, Cinnamon, XFCE, i3 or whatever. I would also be white happy to see D support Qt as well just to have more options. Fair enough. For me, I find GTK/Gnome to be chunky (ex: problematic overuse of margins/padding) and Apple-level "zee must conform!" (ie: under-use of configuration). That, and an outright bad file-chooser ;) But, it's possible I might agree with you if we were talking KDE's defaults - I don't actually use KDE's defaults. But that's kinda my point though: KDE is based around the philosophy of configurability, whereas Gnome (while admittedly does have a certain level of configurability) it very intentionally designed around a philosophy of conformity being superior to configurability. But more importantly than anything else, it seems we all clearly agree: The key (and beauty) of Linux is "user's choice", not "GTK vs Qt". Most distro maintainers want their distro to be as popular as possible. If KDE was a slam dunk like you imply they should be jumping over themselves to make it the default yet they do not. When Ubuntu dropped Unity they had a perfect opportunity to make KDE (or something else) the default yet they did not. Personally, I think you're underestimating the group-think factor in modern software management. From a managerial perspective, there are a LOT of VERY STRONG motivations for promoting conformity over configurability. Not the least of which is "That's the way of Apple/Facebook/etc, and Apple/Facebook/etc are extremely popular/successful". That, combined with both modern tech's current focus on "buzz" and "popularity", AND the practical software-dev-management benefits gained from disregarding the user as anything but collective commodity, creates a VERY potent motivator to prioritize similarly-minded projects over a purely population-driven decision.
Re: D Binding to GUI libraries
On Mon, 22 Oct 2018 00:41:08 -0400, Nick Sabalausky (Abscissa) wrote: > Ultimately, everything points to the same thing: Those who actually CARE > about GTK/Gnome/Unity vs Qt/KDE, typically prefer Qt/KDE. The rest are > just swing votes. Unity 7 and prior for the desktop use Nux, an OpenGL-based widget toolkit. Unity 8 and all mobile versions of Unity use Qt. The application set that Ubuntu shipped with Unity was, I think, heavier on the GTK+ side. I can't answer for "typical" users, but I've preferred GTK+ since 2005. Qt applications feel a bit off to me, and the standard themes were all weirdly bubbly. And while I've used probably a dozen window managers and at least four desktop environments, I've been on MATE for several years now. > As for the distros choice of "which do we make default?", that's really > no surprise and implies nothing significant: The tech industry's current > runway-fashion wind direction is clearly "The user should adapt to the > software", not the other way around. Thus fully explains GTK/GNOME/Unity > as the gatekeepers' current suggestions. Just like Win/Mac: "Actual user > opinions: not relevant." RedHat provides a lot of support and development for GNOME. That makes it a relatively attractive option for other distros.