D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4361 - shared nested classes don't synchronize their parents. Results in a data race.
Summary: shared nested classes don't synchronize their parents. Results in a data race.
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other Windows
: P3 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-06-21 23:29 UTC by Rob Jacques
Modified: 2024-12-13 17:52 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Rob Jacques 2010-06-21 23:29:27 UTC
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;
}
Comment 1 dlangBugzillaToGithub 2024-12-13 17:52:23 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/18258

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB