Topic: Alternative to N4348: std::critical_section
Author: David Krauss <potswa@mac.com>
Date: Sun, 17 May 2015 16:52:48 +0800
Raw View
--Apple-Mail=_040C7C60-A513-436F-AC35-9D6861AC0352
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9305=E2=80=9317, at 1:29 PM, Ville Voutilainen <ville.vouti=
lainen@gmail.com> wrote:
>=20
> That paper hasn't been discussed yet. As far as I understand, it will
> be revisited
> in Kona. I can't make any real predictions on it, but I can
> for-full-disclosure say
> that there is heavy opposition to that proposal due to compatibility issu=
es.
> And in case that wasn't clear, I will be raising such opposition.
Seems to me, the obvious solution would be to opt-in to synchronization thr=
ough functor adaptor classes.
There was a =E2=80=9Cdon=E2=80=99t add internal synchronization=E2=80=9D de=
cision <https://issues.isocpp.org/show_bug.cgi?id=3D34>. But an adaptor wou=
ld only be used to fix the specific problem, outside std::function.
Only a small minority of std::functions with non-const call operators actua=
lly ever face a race condition. They can be internally synchronized, but 99=
..9% just aren=E2=80=99t shared across threads. Existing data races in the w=
ild won=E2=80=99t be fixed by an opt-in. But fixing races in the wild witho=
ut massive breakage is rather a tall order in general.
Ville, what do you think? Is there really an imperative to fix concurrency =
within std::function itself, or would the motivation of N4348 apply here? S=
ee implementation below.
#include <mutex>
// Library proposal:
template< typename ftor, typename mutex >
class basic_critical_section {
ftor f;
mutable mutex m;
public:
basic_critical_section( ftor in )
: f( std::move( in ) ) {}
basic_critical_section( basic_critical_section const & o )
: f( [&o] {
std::lock_guard< mutex > g( o.m );
return o.f; // Return by value. Accomplish the copy before the =
lock is released.
}() )
{}
basic_critical_section( basic_critical_section && o )
: f( [&o] {
std::lock_guard< mutex > g( o.m );
return std::move( o.f );
}() )
{}
template< typename ... arg >
decltype(auto) operator () ( arg && ... a ) {
std::lock_guard< mutex > g( m );
return f( std::forward< arg >( a ) ... );
}
};
template< typename ftor >
using critical_section =3D basic_critical_section< ftor, std::mutex >;
template< typename ftor >
using recursive_critical_section =3D basic_critical_section< ftor, std::rec=
ursive_mutex >;
// TODO: make_critical_section() factory.
// Demo:
#include <thread>
#include <atomic>
#include <unistd.h>
#include <iostream>
std::atomic< int > cnt;
thread_local int const tid =3D cnt ++;
int main() {
auto fn =3D [] { std::cout << tid << '\n'; ::sleep( 1 ); };
critical_section< decltype(fn) > cs( std::move( fn ) );
std::function< void() > f =3D cs;
for ( int i =3D 0; i !=3D 3; ++ i ) {
new std::thread( [&] { for (;;) { f(); } } );
}
::sleep( 10 );
std::exit(0);
}
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_040C7C60-A513-436F-AC35-9D6861AC0352
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9305=
=E2=80=9317, at 1:29 PM, Ville Voutilainen <<a href=3D"mailto:ville.vout=
ilainen@gmail.com" class=3D"">ville.voutilainen@gmail.com</a>> wrote:</d=
iv><br class=3D"Apple-interchange-newline"><div class=3D"">That paper hasn'=
t been discussed yet. As far as I understand, it will<br class=3D"">be revi=
sited<br class=3D"">in Kona. I can't make any real predictions on it, but I=
can<br class=3D"">for-full-disclosure say<br class=3D"">that there is heav=
y opposition to that proposal due to compatibility issues.<br class=3D"">An=
d in case that wasn't clear, I will be raising such opposition.<br class=3D=
""></div></blockquote></div><br class=3D""><div class=3D"">Seems to me, the=
obvious solution would be to opt-in to synchronization through functor ada=
ptor classes.</div><div class=3D""><br class=3D""></div><div class=3D"">The=
re was a =E2=80=9Cdon=E2=80=99t add internal synchronization=E2=80=9D =
<a href=3D"https://issues.isocpp.org/show_bug.cgi?id=3D34" class=3D"">decis=
ion</a>. But an adaptor would only be used to fix the specific problem,&nbs=
p;outside <font face=3D"Courier" class=3D"">std::function</font>.</div=
><div class=3D""><br class=3D""></div><div class=3D"">Only a small minority=
of <font face=3D"Courier" class=3D"">std::function</font>s with non-const =
call operators actually ever face a race condition. They can be internally =
synchronized, but 99.9% just aren=E2=80=99t shared across threads. Existing=
data races in the wild won=E2=80=99t be fixed by an opt-in. But fixing rac=
es in the wild without massive breakage is rather a tall order in general.<=
/div><div class=3D""><br class=3D""></div><div class=3D"">Ville, what do yo=
u think? Is there really an imperative to fix concurrency within <font face=
=3D"Courier" class=3D"">std::function</font> itself, or would the motivatio=
n of N4348 apply here? See implementation below.</div><div class=3D""><br c=
lass=3D""></div><div class=3D""><br class=3D""></div><div class=3D""><font =
face=3D"Courier" class=3D"">#include <mutex><br class=3D""><br class=
=3D"">// Library proposal:</font></div><div class=3D""><font face=3D"Courie=
r" class=3D""><br class=3D""></font></div><div class=3D""><font face=3D"Cou=
rier" class=3D"">template< typename ftor, typename mutex ><br class=
=3D"">class basic_critical_section {<br class=3D""> ftor =
f;<br class=3D""> mutable mutex m;<br class=3D"">public:<=
br class=3D""> basic_critical_section( ftor in )<br class=
=3D""> : f( std::move( in ) ) {}<br class=
=3D""><br class=3D""> basic_critical_section( basic_criti=
cal_section const & o )<br class=3D""> =
: f( [&o] {<br class=3D""> &nbs=
p;std::lock_guard< mutex > g( o.m );<br class=3D""> &nbs=
p; return o.f; // Return by value. Accomplish the=
copy before the lock is released.<br class=3D"">  =
; }() )<br class=3D""> {}<br class=3D"=
"><br class=3D""> basic_critical_section( basic_critical_=
section && o )<br class=3D""> : f( =
[&o] {<br class=3D""> std=
::lock_guard< mutex > g( o.m );<br class=3D""> &n=
bsp; return std::move( o.f );<br class=3D"">  =
; }() )<br class=3D""> {=
}<br class=3D""><br class=3D""> template< typename ...=
arg ><br class=3D""> decltype(auto) operator () ( arg=
&& ... a ) {<br class=3D""> std::l=
ock_guard< mutex > g( m );<br class=3D""> &=
nbsp;return f( std::forward< arg >( a ) ... );<br class=3D""> &=
nbsp; }<br class=3D"">};<br class=3D""><br class=3D"">template< typ=
ename ftor ><br class=3D"">using critical_section =3D basic_critical_sec=
tion< ftor, std::mutex >;<br class=3D""><br class=3D"">template< t=
ypename ftor ><br class=3D"">using recursive_critical_section =3D basic_=
critical_section< ftor, std::recursive_mutex >;<br class=3D""><br cla=
ss=3D"">// TODO: make_critical_section() factory.<br class=3D""><br class=
=3D""><br class=3D"">// Demo:<br class=3D""><br class=3D""></font><span sty=
le=3D"font-family: Courier;" class=3D"">#include <thread></span><br s=
tyle=3D"font-family: Courier;" class=3D""><span style=3D"font-family: Couri=
er;" class=3D"">#include <atomic></span><br style=3D"font-family: Cou=
rier;" class=3D""><font face=3D"Courier" class=3D"">#include <unistd.h&g=
t;<br class=3D"">#include <iostream><br class=3D""><br class=3D"">std=
::atomic< int > cnt;<br class=3D"">thread_local int const tid =3D cnt=
++;<br class=3D""><br class=3D"">int main() {<br class=3D""> &=
nbsp;auto fn =3D [] { std::cout << tid << '\n'; ::sleep( 1 ); }=
;<br class=3D""> critical_section< decltype(fn) > c=
s( std::move( fn ) );<br class=3D""> std::function< vo=
id() > f =3D cs;<br class=3D""><br class=3D""> for ( i=
nt i =3D 0; i !=3D 3; ++ i ) {<br class=3D""> &nb=
sp;new std::thread( [&] { for (;;) { f(); } } );<br class=3D""> &=
nbsp; }<br class=3D""><br class=3D""> ::sleep( 10 );=
<br class=3D""> std::exit(0);<br class=3D"">}<br class=3D=
""></font></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_040C7C60-A513-436F-AC35-9D6861AC0352--
.