Thread overview
[Issue 12133] New: Relaxed read-modify-write for shared lvalues
Feb 11, 2014
Stanislav Blinov
Feb 11, 2014
Andrej Mitrovic
Feb 11, 2014
Stanislav Blinov
Feb 11, 2014
Andrej Mitrovic
Feb 11, 2014
Andrej Mitrovic
Feb 11, 2014
Andrej Mitrovic
Feb 11, 2014
Stanislav Blinov
Feb 12, 2014
Stanislav Blinov
Feb 15, 2014
Stanislav Blinov
February 11, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133

           Summary: Relaxed read-modify-write for shared lvalues
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: druntime
        AssignedTo: nobody@puremagic.com
        ReportedBy: stanislav.blinov@gmail.com


--- Comment #0 from Stanislav Blinov <stanislav.blinov@gmail.com> 2014-02-11 15:31:31 PST ---
TDPL prohibits using operators on shared variables. I.e. this:

shared int i;
++i;

is illegal. It is stated that core.atomic should be used instead:

shared int i;
atomicOp!"+="(i, 1);

However, there are cases when this can introduce unnecessary performance loss: e.g. private shared variables that are only ever accessed under a lock.

I'm proposing to add two functions to core.atomic to allow for operations on shared variables without atomicOp()'s performance penalties:

1) localOp:

performs and acquire-op-release, e.g.:

shared int i;
auto v = localOp!"+="(i, 1);

Useful when there's still need for ordering. Though I don't really like the name "localOp".

2) assumeLocal:

converts shared lvalue to a non-shared lvalue, e.g:

shared int i;
++assumeLocal(i);

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 11, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich@gmail.com


--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2014-02-11 15:36:23 PST ---
(In reply to comment #0)
> 2) assumeLocal:
> 
> converts shared lvalue to a non-shared lvalue, e.g:
> 
> shared int i;
> ++assumeLocal(i);

shared int i;
++cast()i;

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 11, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133



--- Comment #2 from Stanislav Blinov <stanislav.blinov@gmail.com> 2014-02-11 15:39:09 PST ---
(In reply to comment #1)

> shared int i;
> ++cast()i;

cast()i would cast away everything, including const, silently :)

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 11, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133



--- Comment #3 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2014-02-11 15:49:51 PST ---
(In reply to comment #2)
> (In reply to comment #1)
> 
> > shared int i;
> > ++cast()i;
> 
> cast()i would cast away everything, including const, silently :)

Oops. Maybe something like:

-----
template Unshared(T)
{
         static if (is(T U == shared inout const U)) alias Unshared = U;
    else static if (is(T U == shared inout       U)) alias Unshared = U;
    else static if (is(T U == shared       const U)) alias Unshared = U;
    else static if (is(T U == shared             U)) alias Unshared = U;
    else                                             alias Unshared = T;
}

ref unshared(T)(ref T var)
{
    return *cast(Unshared!T*)&var;
}

void main()
{
    shared int x;
    ++unshared(x);
    assert(x == 1);
}
-----

Unshared code based off of Unqual.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 11, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133



--- Comment #4 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2014-02-11 15:50:29 PST ---
(In reply to comment #3)
> template Unshared(T)
> {
>          static if (is(T U == shared inout const U)) alias Unshared = U;
>     else static if (is(T U == shared inout       U)) alias Unshared = U;
>     else static if (is(T U == shared       const U)) alias Unshared = U;
>     else static if (is(T U == shared             U)) alias Unshared = U;
>     else                                             alias Unshared = T;
> }

Uhh that should teach me to copy-paste, the RHS should simply strip shared, not strip all the qualifiers.

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 11, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133



--- Comment #5 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2014-02-11 15:51:03 PST ---
(In reply to comment #4)
> Uhh that should teach me to copy-paste, the RHS should simply strip shared, not strip all the qualifiers.

Fixed:

template Unshared(T)
{
         static if (is(T U == shared inout const U)) alias Unshared = inout
const U;
    else static if (is(T U == shared inout       U)) alias Unshared = inout U;
    else static if (is(T U == shared       const U)) alias Unshared = const U;
    else static if (is(T U == shared             U)) alias Unshared = U;
    else                                             alias Unshared = T;
}

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 11, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133



--- Comment #6 from Stanislav Blinov <stanislav.blinov@gmail.com> 2014-02-11 15:57:16 PST ---
Something a bit less involving :)

ref auto assumeLocal(T)(ref shared T var) @trusted pure nothrow
{
    return *cast(T*)&var;
}

I should've probably noted that I already have implementations for both functions in mind, just not in the state of pull request yet.

But comments, suggestions, objections and improvements are key!

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 12, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133



--- Comment #7 from Stanislav Blinov <stanislav.blinov@gmail.com> 2014-02-11 16:01:43 PST ---
See also the discussion thread:

http://forum.dlang.org/thread/moyyibrpnnmrrovylkui@forum.dlang.org

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 15, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133


Stanislav Blinov <stanislav.blinov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull


--- Comment #8 from Stanislav Blinov <stanislav.blinov@gmail.com> 2014-02-14 22:15:42 PST ---
Pull request for assumeLocal():
https://github.com/D-Programming-Language/druntime/pull/724

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 16, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12133


Andrei Alexandrescu <andrei@erdani.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei@erdani.com


--- Comment #9 from Andrei Alexandrescu <andrei@erdani.com> 2014-03-15 20:38:58 PDT ---
localOp should be atomicOpRelaxed

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