[Issue 20867] New: class subtyping doen't work in separate files
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Wed May 27 21:21:19 UTC 2020
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 at puremagic.com
Reporter: mingwu at 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);
}
--------------------------------------------------------------------------------
$ dmd queue.d # succeed.
$ cat t.d # put T and f() in separate file t.d:
--------------------------------------------------------------------------------
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)))
--
More information about the Digitalmars-d-bugs
mailing list