On Wednesday, 26 February 2014 at 11:24:58 UTC, bearophile wrote:
Ali Çehreli:

               synchronized {
                   // Switch to the next printer
                   printers = printers[1..$];
               }

This doesn't work:

printers.popFront();

Yes, because typeof(printers) == shared. I'm wondering why front() works.

           try {
               synchronized {
(cast(Printer)printers.front).print(lines.front);
               }

It it a good idea to define Printer.print like this to remove that cast?

void print(string line) shared

No it is not, because the implementation of print() would be invalid then:

    void print(string line) shared
    {
enforce(ink != 0, new OutOfInk); // ink != 0 is not valid code
        writefln("%s: %s", id, line);
--ink; // --ink is not valid code
    }

By declaring the method "shared" you promise that any acess to shared data in this method is safe. Using naked operators on shared scalar variables will eventually be disallowed, you'll have to explicitly use atomic operations.

You'd also have to synchronize access to id member, because it is public. Although "immutable" means "implicitly shared", id being public means that potentionally one thread could be performing assigment to it while another one reads from it. Slices are two machine words, so atomicity of reads/writes is not implicitly guaranteed.

The cast in this case is safe and better approach because all access to "printers" is synchronized. If/when https://d.puremagic.com/issues/show_bug.cgi?id=12133 and the corresponding pull is accepted, the cast could be replaced with

    printers.assumeLocal.front.print(lines.front);

which states the intent even more clearly, IMO.

Reply via email to