digitalmars.D.bugs - [Issue 20867] New: class subtyping doen't work in separate files
- d-bugmail puremagic.com (141/141) May 27 2020 https://issues.dlang.org/show_bug.cgi?id=20867
https://issues.dlang.org/show_bug.cgi?id=20867 Issue ID: 20867 Summary: class subtyping doen't work in separate files Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nobody puremagic.com Reporter: mingwu gmail.com Created attachment 1791 --> https://issues.dlang.org/attachment.cgi?id=1791&action=edit class subtyping doen't work in separate files Put the code on page: https://tour.dlang.org/tour/en/multithreading/synchronization-sharing in to queue.d, then add subtyping and a test func f(): ... private T[] elements; public: alias elements this; // add this line ... // test f() class T{} void f() { auto q = new shared(SafeQueue!(shared T)); writeln(q.length); } If f() is in the same file queue.d, the code can compile; if it's in a separate file, compile will fail. $ cat queue.d -------------------------------------------------------------------------------- import std.stdio; import std.concurrency : receiveOnly, send, spawn, Tid, thisTid; import core.atomic : atomicOp, atomicLoad; /* Queue that can be used safely among different threads. All access to an instance is automatically locked thanks to synchronized keyword. */ synchronized class SafeQueue(T) { // Note: must be private in synchronized // classes otherwise D complains. private T[] elements; public: alias elements this; void push(T value) { elements ~= value; } /// Return T.init if queue empty T pop() { import std.array : empty; T value; if (elements.empty) return value; value = elements[0]; elements = elements[1 .. $]; return value; } } /* Safely print messages independent of number of concurrent threads. Note that variadic parameters are used for args! That is args might be 0 .. N parameters. */ void safePrint(T...)(T args) { // Just executed by one concurrently synchronized { import std.stdio : writeln; writeln(args); } } void threadProducer(shared(SafeQueue!int) queue, shared(int)* queueCounter) { import std.range : iota; // Push values 1 to 10 foreach (i; 1..11) { queue.push(i); safePrint("Pushed ", i); atomicOp!"+="(*queueCounter, 1); } } void threadConsumer(Tid owner, shared(SafeQueue!int) queue, shared(int)* queueCounter) { int popped = 0; while (popped != 10) { auto i = queue.pop(); if (i == int.init) continue; ++popped; // safely fetch current value of // queueCounter using atomicLoad safePrint("Popped ", i, " (Consumer pushed ", atomicLoad(*queueCounter), ")"); } // I'm done! owner.send(true); } void main() { auto queue = new shared(SafeQueue!int); shared int counter = 0; spawn(&threadProducer, queue, &counter); auto consumer = spawn(&threadConsumer, thisTid, queue, &counter); auto stopped = receiveOnly!bool; assert(stopped); } class T{} void f() { auto q = new shared(SafeQueue!(shared T)); writeln(q.length); } -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- import std.stdio; import queue; class T{} void f() { auto q = new shared(SafeQueue!(shared T)); writeln(q.length); } -------------------------------------------------------------------------------- $ dmd t.d t.d(9): Error: no property length for type shared(queue.SafeQueue!(shared(T))) --
May 27 2020