This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
debug mode contention
- From: François Dumont <francois dot cppdevs at free dot fr>
- To: libstdc++ at gcc dot gnu dot org
- Date: Fri, 01 Oct 2010 15:24:59 +0200
- Subject: debug mode contention
Hi
Here is my reflection on the debug mode contention issue.
What has to be protected ?
C++ Standard do not say anything about multi-threading and it is
well known that std containers are not thread safe, users are supposed
to synchronize access to them when used in a multi-threaded environment.
However, using read-only methods on a single container instance from
different threads should work fine. The problem is that normal mode
read-only operations are not necessarily read-only anymore in the debug
mode. The debug version of containers needs to track all the iterators
generated from it in order to signal invalid usage when the element
pointed to by those iterators is destroyed. This is why safe containers
needs to synchronize access to the iterator lists that are populated
each time an iterator is created or destroyed
Current situation
For the moment libstdc++ synchronize all operations on both safe
sequence and safe iterators. Moreover synchronization is done thanks to
a unique mutex instance so even reading 2 different containers from 2
different threads will imply contention.
Planned modifications
Here is the modification I have plan to acheive
1. Remove synchronization on safe iterator. Safe iterators should use
safe sequence mutex when they need to update the sequence list of
iterators. For correct encapsulation safe iterators should even not lock
anything anymore but rather ask the safe sequence to add/remove then
from their internal list.
2. Offer a mutex instance to each safe sequence rather than a single
global mutex. This is going to impact binary compatibility of the lib so
it might not be possible for the moment, just let me know.
3. Limit creation of safe iterators so that we do not have to populate
the safe sequence with new entries for nothing. Here is for instance the
_M_is_begin implementation used to detect when an iterator is the
sequence begin:
bool _M_is_begin() const
{ return *this == _M_get_sequence()->begin(); }
it should rather be:
bool _M_is_begin() const
{ return base() == _M_get_sequence()->_M_base().begin(); }
The new version do not generate any safe iterator avoiding the lock
on the safe iterator lists. There are many methods in safe container
themselves that are based on safe iterators already and that I am going
to rewrite to use normal iterator instead. Doing so will not only reduce
contention but also enhance debug mode performance.
4. Limit globally the places where locks are taken. There are many
methods that are invalid to call from different threads without user
synchronization, internal debug mode synchronization should not hide a
user mistake.
François