[boost] Proposal for a thread "collision" detector

8 views
Skip to first unread message

Gaetano Mendola

unread,
Jun 14, 2013, 6:43:36 AM6/14/13
to bo...@lists.boost.org
I would like to know if Boost community could be interested in
adopting a check mechanism that is able to detect if a not supposed
thread safe class is used by multiple threads in unsafe way. This
tecnique has saved us a lot of headache especially when code refactoring
on old code is performed.

Better to explain it, without enter in the detail of the implementation,
with some examples:


Example: Queue implementation non thread-safe but still usable if clients
are synchronized somehow.


class NonThreadSafeQueue {
public:
...
void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... }
int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... }
...
private:
DFAKE_MUTEX(push_pop_);
};


Example: Queue implementation not usable even if clients are synchronized,
so only one thread in the class life cycle can use the two members
push/pop.

In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the
specified critical section the first time a thread enters push or
pop, from that time on only that thread is allowed to execute push
or pop.

class NonThreadSafeQueue {
public:
...
void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
...
private:
DFAKE_MUTEX(push_pop_);
};


Example: Class that has to be contructed/destroyed on same thread, it has
a "shareable" method (with external syncronization) and a not
shareable method (even with external synchronization).

In this case 3 Critical sections have to be defined


class ExoticClass {
public:
ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }

void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... }
void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
...
private:
DFAKE_MUTEX(ctor_dtor_)
DFAKE_MUTEX(shareable_section_)
};


DFAKE_SCOPED_LOCK will "throw an exception" or will call an "abort" in
case of check failed.

This tecnique doesn't involve real lock/unlock but uses atomic operations, also
the various macros DFAKE_XXXXXXXXX are defined void when NDEBUG is defined.


Any comment is appreciated.


Regards
Gaetano Mendola









_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hartmut Kaiser

unread,
Jun 16, 2013, 10:32:09 AM6/16/13
to bo...@lists.boost.org
I'd be interested.

Regards Hartmut
---------------
http://boost-spirit.com
http://stellar.cct.lsu.edu

Ivan Sorokin

unread,
Jun 18, 2013, 3:22:24 AM6/18/13
to bo...@lists.boost.org, men...@gmail.com
On 14.06.2013 14:43, Gaetano Mendola wrote:
> I would like to know if Boost community could be interested in
> adopting a check mechanism that is able to detect if a not supposed
> thread safe class is used by multiple threads in unsafe way. This
> tecnique has saved us a lot of headache especially when code refactoring
> on old code is performed.

I used the same technique and it helped me a lot. I had a bit different
interface though.

1. Mutex-like class that asserts that there is no two threads attempt to
lock it simultaneously (similar to your DFAKE_SCOPED_LOCK lock type).

Note, that it is convenient that this class is copyable so it can be
used in copyable classes.

2. Class with the following interface:

struct thread_affinity_checker : noncopyable
{
thread_affinity_checker();
~thread_affinity_checker();

void check_current_thread() const;
};

Its constructor remembers current thread-id. Destructor and
check_current_thread() function asserts that id of current thread is the
same as remembered in constructor. This class is useful if some class
has thread affinity e.g. HWND (similar to your
DFAKE_SCOPED_LOCK_THREAD_LOCKED).

Generally I think that it's very useful to have DFAKE_SCOPED_LOCK in all
appropriate classes in boost (containers especially). Possibly for small
classes like smart-pointers, this check is costly, so it should be
enabled only with special #define. Once it took me a lot of time to
debug concurrent access to shared_ptr (assignment from it in one thread
and assignment to it in another). If this technique existed back then it
saved me a lot of time.

Gaetano Mendola

unread,
Jun 24, 2013, 4:33:34 PM6/24/13
to bo...@lists.boost.org, hartmut...@gmail.com
To whom is interested in it, you can find in my blog

http://cpp-today.blogspot.it/2008/06/threading-mess.html
http://cpp-today.blogspot.it/2008/06/threading-mess-2.html

an early implementation of the technique. My current implementation is
different than that one in the blog in the sense that the macros have
a different name (see my examples above) and it's using not GCC atomic
operations but tbb::atomic.

I don't know how to proceed (if) with the proposal for boost, for sure
I have to modify my current implementation and write it in terms of
boost::atomic (it uses tbb::atomic at the moment).

I have also "donated" the code to google chromium project long time ago
(I'm not even sure if they are still using it or not) and I don't know
if that can be an issue for a boost adoption.
Reply all
Reply to author
Forward
0 new messages