gcc/libstdc++-v3
Jonathan Wakely 6cf0040fff libstdc++: Improve std::lock algorithm
The current std::lock algorithm is the one called "persistent" in Howard
Hinnant's https://howardhinnant.github.io/dining_philosophers.html post.
While it tends to perform acceptably fast, it wastes a lot of CPU cycles
by continuously locking and unlocking the uncontended mutexes.
Effectively, it's a spin lock with no back-off.

This replaces it with the one Howard calls "smart and polite". It's
smart, because when a Mi.try_lock() call fails because mutex Mi is
contended, the algorithm reorders the mutexes until Mi is first, then
calls Mi.lock(), to block until Mi is no longer contended.  It's
polite because it uses std::this_thread::yield() between the failed
Mi.try_lock() call and the Mi.lock() call. (In reality it uses
__gthread_yield() directly, because using this_thread::yield() would
require shuffling code around to avoid a circular dependency.)

This version of the algorithm is inspired by some hints from Howard, so
that it has strictly bounded stack usage. As the comment in the code
says:

// This function can recurse up to N levels deep, for N = 1+sizeof...(L1).
// On each recursion the lockables are rotated left one position,
// e.g. depth 0: l0, l1, l2; depth 1: l1, l2, l0; depth 2: l2, l0, l1.
// When a call to l_i.try_lock() fails it recurses/returns to depth=i
// so that l_i is the first argument, and then blocks until l_i is locked.

The 'i' parameter is the desired permuation of the lockables, and the
'depth' parameter is the depth in the call stack of the current
instantiation of the function template. If i == depth then the function
calls l0.lock() and then l1.try_lock()... for each lockable in the
parameter pack l1.  If i > depth then the function rotates the lockables
to the left one place, and calls itself again to go one level deeper.
Finally, if i < depth then the function returns to a shallower depth,
equivalent to a right rotate of the lockables.  When a call to
try_lock() fails, i is set to the index of the contended lockable, so
that the next call to l0.lock() will use the contended lockable as l0.

This commit also replaces the std::try_lock implementation details. The
new code is identical in behaviour, but uses a pair of constrained
function templates. This avoids instantiating a class template, and is a
litle simpler to call where used in std::__detail::__lock_impl and
std::try_lock.

Signed-off-by: Jonathan Wakely <jwakely@redhat.com>

libstdc++-v3/ChangeLog:

	* include/std/mutex (__try_to_lock): Move to __detail namespace.
	(struct __try_lock_impl): Replace with ...
	(__detail::__try_lock_impl<Idx>(tuple<Lockables...>&)): New
	function templates to implement std::try_lock.
	(try_lock): Use new __try_lock_impl.
	(__detail::__lock_impl(int, int&, L0&, L1&...)): New function
	template to implement std::lock.
	(lock): Use __lock_impl.
2021-06-21 18:29:58 +01:00
..
config ctype support for libstdc++ on VxWorks 2021-05-04 21:49:43 -03:00
doc libstdc++: Add feature test macro for heterogeneous lookup in unordered containers 2021-06-04 15:59:37 +01:00
include libstdc++: Improve std::lock algorithm 2021-06-21 18:29:58 +01:00
libsupc++ libstdc++: Implement LWG 3465 for std::compare_partial_order_fallback [PR101056] 2021-06-14 14:04:45 +01:00
po Update copyright years. 2021-01-04 10:26:59 +01:00
python libstdc++: Fix installation of python hooks [PR 99453] 2021-06-01 13:29:34 +01:00
scripts libstdc++: Allow lualatex to be used for Doxygen PDF 2021-05-17 12:13:41 +01:00
src libstdc++: [_GLIBCXX_DEBUG] Enhance rendering of assert message 2021-05-26 21:50:17 +02:00
testsuite libstdc++: Implement new views::split as per P2210 2021-06-20 12:47:18 -04:00
acinclude.m4 ctype support for libstdc++ on VxWorks 2021-05-04 21:49:43 -03:00
aclocal.m4
ChangeLog Daily bump. 2021-06-21 00:16:25 +00:00
ChangeLog-1998
ChangeLog-1999
ChangeLog-2000
ChangeLog-2001
ChangeLog-2002
ChangeLog-2003
ChangeLog-2004
ChangeLog-2005
ChangeLog-2006
ChangeLog-2007
ChangeLog-2008
ChangeLog-2009
ChangeLog-2010
ChangeLog-2011
ChangeLog-2012
ChangeLog-2013
ChangeLog-2014
ChangeLog-2015
ChangeLog-2016
ChangeLog-2017
ChangeLog-2018
ChangeLog-2019
ChangeLog-2020 libstdc++: Fix typo in ChangeLog-2020 2021-01-13 11:02:13 +00:00
config.h.in libstdc++: Remove _GLIBCXX_USE_INT128 autoconf macro 2021-05-04 12:07:09 +01:00
configure ctype support for libstdc++ on VxWorks 2021-05-04 21:49:43 -03:00
configure.ac libstdc++: Remove _GLIBCXX_USE_INT128 autoconf macro 2021-05-04 12:07:09 +01:00
configure.host Scope libstdc++ configuration for vxworks to all versions 2020-10-22 16:40:57 +00:00
crossconfig.m4 Scope libstdc++ configuration for vxworks to all versions 2020-10-22 16:40:57 +00:00
fragment.am libstdc++: Add C++ runtime support for new 128-bit long double format 2020-12-16 23:25:01 +00:00
linkage.m4
Makefile.am Update copyright years. 2021-01-04 10:26:59 +01:00
Makefile.in libstdc++: Add C++ runtime support for new 128-bit long double format 2020-12-16 23:25:01 +00:00
README

file: libstdc++-v3/README

New users may wish to point their web browsers to the file
index.html in the 'doc/html' subdirectory.  It contains brief
building instructions and notes on how to configure the library in
interesting ways.