www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 4361] New: shared nested classes don't synchronize their parents. Results in a data race.

http://d.puremagic.com/issues/show_bug.cgi?id=4361

           Summary: shared nested classes don't synchronize their parents.
                    Results in a data race.
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: sandford jhu.edu


--- Comment #0 from Rob Jacques <sandford jhu.edu> 2010-06-21 23:29:27 PDT ---
shared nested classes don't synchronize their parents when they synchronize
themselves. An example follows which demonstrates when and where monitors are
created and an example of the data race which can result. In theory, the
solution is to set the nested object's monitor pointer to equal its parents. In
order for nested classes to be composible, (i.e. so that a nested class can
have a nested class) this forces the monitor to be allocated on eagerly(if not
already allocated) when the nested object is allocated. This is opposed to the
current scheme where monitors are only allocated on first use. Naturally, only
shared types would require this allocation. This has the benefit of eliminating
excess monitors and locks. 

shared class Foo {
    int y;
    shared class Bar {  // shared isn't necessary here, but included for
clarity
        synchronized int x()  { return y; }
        synchronized int bigSleep(int _y)  {
            y = -_y;
            Thread.sleep(10_000_000);
            return y = _y; }
    }
    synchronized int z()  { return y; }
}

void* getMonitor(Object h)
{
    return cast(void*) (cast(void**) h)[1];
}

void main(string[] args) {
    shared foo = new  Foo();
    auto bar = foo.new Bar;

    writeln( "Both monitors init to null:       ",
getMonitor(foo),'\t',getMonitor(bar) );

    synchronized(foo) {
        foo.y = 5;
    }

    writeln( "synchronizing sets foo's monitor: ",
getMonitor(foo),'\t',getMonitor(bar) );
    foo.y = bar.x;

    writeln( "synchronizing sets bar's monitor: ",
getMonitor(foo),'\t',getMonitor(bar) );

    assert( getMonitor(foo) !=  getMonitor(bar) );

    // Synchronizing bar doesn't synchronize foo
    auto thread = new Thread( (){ writeln(bar.bigSleep(15) ); }  );
    thread.start;
    Thread.sleep(10_000);
    writeln(foo.z);   // error prints  -15, should print 5 or 15
    writeln(bar.x);   // correctly prints 5 or 15
    thread.join();    

    return;
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 21 2010