This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]