Threads and Smart Ptrs
Greetings, everyone. I'm currently having some trouble with a heavily multithreaded app which uses objects shared between threads via smart pointers. It's a multi-user application, where each user has a thread, and when one user sends a message to another (or broadcasts to all), a message object is created, and a smart pointer to that message is put into a queue for each thread. I'm using pthread_mutex for locking the queues for each thread. This program will sometimes work flawlessly for hours, and other times it will die within moments of starting. Pretty much every time it dies, it's because the message object has been freed while there are still smart pointers pointing to it. I know that the recent version of the smart pointer library was supposed to have added thread-safety to it, but I'm wondering if anyone else is having similar troubles. I'm using gcc 3.0.3 on Linux, and boost 1.27. I also discovered some things in the gcc documentation having to do with threads, (eg: when you compile the compiler, you have to tell it to build multi-threaded programs). And there are various threading flags that can be used during a compile, and I'm not sure which to use (or all of them?): -D_PTHREADS -D_REENTRANT -pthread : I'm using all those right now. Is that wrong? Any help would be greatly appreciated. It's driving me mad! :) Regards, Colin -- Colin Fox CF Consulting Inc. cfox@telus.net
From: "Colin Fox"
Greetings, everyone.
I'm currently having some trouble with a heavily multithreaded app which uses objects shared between threads via smart pointers.
It's a multi-user application, where each user has a thread, and when one user sends a message to another (or broadcasts to all), a message object is created, and a smart pointer to that message is put into a queue for each thread.
I'm using pthread_mutex for locking the queues for each thread.
This program will sometimes work flawlessly for hours, and other times it will die within moments of starting. Pretty much every time it dies, it's because the message object has been freed while there are still smart pointers pointing to it.
I know that the recent version of the smart pointer library was supposed to have added thread-safety to it, but I'm wondering if anyone else is having similar troubles.
I'm using gcc 3.0.3 on Linux, and boost 1.27.
Can you simplify the program to the bare minimum that still has the problem? Also, does the CVS version of shared_ptr work? (It now uses a pthread_mutex on Linux and not atomic intructions.)
On Fri, 2002-02-15 at 11:31, Peter Dimov wrote:
From: "Colin Fox"
<..> I'm using gcc 3.0.3 on Linux, and boost 1.27.
Can you simplify the program to the bare minimum that still has the problem?
Not very easily, but if I can't make any progress, I'll do that.
Also, does the CVS version of shared_ptr work? (It now uses a pthread_mutex on Linux and not atomic intructions.)
Thanks, I'll give it a shot. I noticed that one time that it died, it died within the atomic code, so maybe this will help. (Crossing fingers). -- Colin Fox CF Consulting Inc. cfox@crystalcherry.com
On Fri, 2002-02-15 at 11:31, Peter Dimov wrote:
From: "Colin Fox"
<..> I'm using gcc 3.0.3 on Linux, and boost 1.27.
Can you simplify the program to the bare minimum that still has the
From: "Colin Fox"
Not very easily, but if I can't make any progress, I'll do that.
OK, let me explain the exact level of thread safety provided by shared_ptr; it might be of help. shared_ptr (in 1.27+) is (should be) thread neutral. A class X is thread neutral when: * Accessing two different objects of class X is safe, even when they are equivalent copies; * Accessing the same object is safe only when all accesses are read accesses; otherwise the behavior is undefined. For example, under the pthreads memory model all C types are thread neutral. This means that: shared_ptr p; // thread 1 shared_ptr q(p); // read p // thread 2 shared_ptr r(p); // read p is safe. // thread 1 q.reset(); // write q // thread 2 r.reset(); // write r is safe. // thread 1 shared_ptr s(p); // read p // thread 2 p.reset(); // write p is undefined behavior. If your program doesn't read/write or write/write (to) the same shared_ptr simultaneously, and still misbehaves, then there is a bug in shared_ptr that we'll have to track down.
On Sat, 2002-02-16 at 03:37, Peter Dimov wrote: <..>
OK, let me explain the exact level of thread safety provided by shared_ptr; it might be of help.
shared_ptr (in 1.27+) is (should be) thread neutral. A class X is thread neutral when:
* Accessing two different objects of class X is safe, even when they are equivalent copies; * Accessing the same object is safe only when all accesses are read accesses; otherwise the behavior is undefined. <..> If your program doesn't read/write or write/write (to) the same shared_ptr simultaneously, and still misbehaves, then there is a bug in shared_ptr that we'll have to track down.
The problem I'm having is simply that one thread destroys it's smart pointer to an object, and the object gets destroyed while another thread is still using that object. Once these shared objects are created, all threads only read them, so it's not that kind of read/write conflict. I just need the object to hang around until no more threads need it. I got the CVS version of boost, which you suggested, and had my program running all night last night. No problems so far. Perhaps this solves it. -- Colin Fox CF Consulting Inc. cfox@crystalcherry.com
From: "Colin Fox"
I got the CVS version of boost, which you suggested, and had my program running all night last night. No problems so far. Perhaps this solves it.
Let's hope so. I presume you're on a multiprocessor? Could you please also try my latest attempt, that uses lwm_linux.hpp on linux instead of the generic lwm_pthreads.hpp? It's much faster than the pthreads version when there's no contention but there's no point being faster if it's incorrect.
On Sat, 2002-02-16 at 10:50, Peter Dimov wrote:
From: "Colin Fox"
I got the CVS version of boost, which you suggested, and had my program running all night last night. No problems so far. Perhaps this solves it.
Let's hope so. I presume you're on a multiprocessor? Could you please also try my latest attempt, that uses lwm_linux.hpp on linux instead of the generic lwm_pthreads.hpp? It's much faster than the pthreads version when there's no contention but there's no point being faster if it's incorrect.
Yes, I forgot to mention that - I'm developing on a dual processor box. How do I try the latest attempt? Is that what's in CVS, or do I need something else? Speed will become important, because eventually this is going to have to handle a fairly high thread & activity load. But I completely agree that correctness comes first. :) -- Colin Fox CF Consulting Inc. cfox@crystalcherry.com
On Sat, 2002-02-16 at 10:50, Peter Dimov wrote:
From: "Colin Fox"
I got the CVS version of boost, which you suggested, and had my
From: "Colin Fox"
running all night last night. No problems so far. Perhaps this solves it.
Let's hope so. I presume you're on a multiprocessor? Could you please also try my latest attempt, that uses lwm_linux.hpp on linux instead of the generic lwm_pthreads.hpp? It's much faster than the pthreads version when there's no contention but there's no point being faster if it's incorrect.
Yes, I forgot to mention that - I'm developing on a dual processor box.
I kind of suspected that. This probably means that the atomic_* functions don't synchronize memory (they are supposed to, but...)
How do I try the latest attempt? Is that what's in CVS, or do I need something else?
Yes, it's in CVS. I've also added a test for thread safety, libs/smart_ptr/shared_ptr_mt_test.cpp.
Speed will become important, because eventually this is going to have to handle a fairly high thread & activity load. But I completely agree that correctness comes first. :)
Copying a shared_ptr is about 3.4 times faster with the specialized version, but it depends on atomic_inc and atomic_dec_and_test as well, so it probably won't work. Oh well.
Hi Colin,
I had soimilar problem using boost 1.25.8.
Here is my own modified implementation of smart
pointers based on the non thread safe boost one.
Hope this will help you,
Seb.
#ifndef BOOST_SMART_PTR_HPP
#define BOOST_SMART_PTR_HPP
#include
=).
template<typename T>
struct less< boost::shared_ptr<T> >
: binary_function
participants (3)
-
Colin Fox
-
Peter Dimov
-
Sebastien Marc