JHaack
asked on
Smart Pointers and Multithreading
I have a SmartPtr class that implements reference counting and garbage collections. First of all, I am weary about it's completeness. Is there a complete SmartPtr class that acts exactly (or nearly) like a regular pointer available. Second, since threads each have their own stack, are smart pointers useful for multithreading? It seems to me that since threads share resources (heap, GDI, etc), the smart pointer would be ideal for multithreading memory management. Ultimately, I'm looking for a complete smart pointer and a good discussion (or book/article) on the various uses of smart pointers, including their applicability to multithreading.
One good reference I saw is in Scott Meyer's More Effective C++: Item 28 on page 159. Actually, his books are really good (Effective C++).
ASKER
I'm looking for the application of smart pointers in multithreading. I agree that "More Effective C++" is a good reference on smart pointers, but it doesn't really provide me with any information that I didn't already know. As I indicated in the question, I have already implemented a smart pointer. Beyond that, I'm looking for a commercial-level/standard smart pointer and, most importantly, a discussion on the application of smart pointers in multithreading.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
whoops, it screwed up my spacing on the timeline:
Thread 1: fetches ref count (temp= meef.m_nRefCount; // == 2)
Thread 1: increments it (temp++)
(task switch)
Thread 2: fetches ref count (temp = meef.m_nRefCount; // == 2)
Thread 2: increments it (temp++)
Thread 2: stores ref count (meef.m_nRefCount = temp; // == 3)
(task switch)
Thread 1: stores ref count (meef.m_nRefCount = temp; // == 3!!)
Thread 1: fetches ref count (temp= meef.m_nRefCount; // == 2)
Thread 1: increments it (temp++)
(task switch)
Thread 2: fetches ref count (temp = meef.m_nRefCount; // == 2)
Thread 2: increments it (temp++)
Thread 2: stores ref count (meef.m_nRefCount = temp; // == 3)
(task switch)
Thread 1: stores ref count (meef.m_nRefCount = temp; // == 3!!)
ASKER
I'm pretty sure I can synchronize my smart pointer to be thread safe. However, I am a little unclear about how to share smart pointers between threads. I've always used handles to create shared pointers. Isn't there a problem in passing pointers between threads? Specifically, I want to allocate data on the heap using a smart pointer in the primary thread. Secondary threads will then use the heap data, incrementing the refcount when they start and decrementing it when they finish - not worrying about whether the heap should be freed. If you could provide a snippet of code that illustrates the concept, I would greatly appreciate it. Otherwise, thank you for the excellent help that you've already provided.
P.S. Do you know of any good articles/books on smart pointers and multithreading?
P.S. Do you know of any good articles/books on smart pointers and multithreading?
I haven't run across any articles or books that deal with smart pointers in a multithreaded context.
generally, this is how I would go about the scenario you describe (this isn't garuanteed to be syntactically correct, but it is conceptually correct):
struct ThreadArgs
{
MeefSmartPointer ptr; // MeefSmartPointer is a smart pointer to
// type CMeef
};
void thread1(void *pArg)
{
ThreadArgs *p = (ThreadArgs *)pArg;
MeefSmartPointer ptr = p->ptr; // meef ref count == 3
delete p; // free up arguments // meef ref count == 2
while(1)
{
// do our thing with our reference to the shared data in ptr
}
// when we exit, we decrement meef's ref count
}
#define STACK_SIZE (1<<14) // stack size of 16K
void main()
{
MeefSmartPtr ptr = new CMeef; // increments ref count to 1
ThreadArgs *p = new ThreadArgs;
p->ptr = ptr; // ref count = 2 now
_beginthread(thread1, STACK_SIZE, (void *)p);
// worker thread deletes arguments
while(1)
{
// do our main thread thing
}
// when we exit, we decrement the meef's ref count
}
This allows both threads to acces the data (the CMeef object) and keeps a reference count to it. As long as the ref counting is implemented as I described above, this is thread safe. Note that since we're never really sharing a smart pointer between two threads (i.e. the main thread and thread1 do not access the passed smart pointer itself at the same time, only the CMeef object), you don't need to worry about synchronizing the smart pointer's copy constructors/assignment operators.
generally, this is how I would go about the scenario you describe (this isn't garuanteed to be syntactically correct, but it is conceptually correct):
struct ThreadArgs
{
MeefSmartPointer ptr; // MeefSmartPointer is a smart pointer to
// type CMeef
};
void thread1(void *pArg)
{
ThreadArgs *p = (ThreadArgs *)pArg;
MeefSmartPointer ptr = p->ptr; // meef ref count == 3
delete p; // free up arguments // meef ref count == 2
while(1)
{
// do our thing with our reference to the shared data in ptr
}
// when we exit, we decrement meef's ref count
}
#define STACK_SIZE (1<<14) // stack size of 16K
void main()
{
MeefSmartPtr ptr = new CMeef; // increments ref count to 1
ThreadArgs *p = new ThreadArgs;
p->ptr = ptr; // ref count = 2 now
_beginthread(thread1, STACK_SIZE, (void *)p);
// worker thread deletes arguments
while(1)
{
// do our main thread thing
}
// when we exit, we decrement the meef's ref count
}
This allows both threads to acces the data (the CMeef object) and keeps a reference count to it. As long as the ref counting is implemented as I described above, this is thread safe. Note that since we're never really sharing a smart pointer between two threads (i.e. the main thread and thread1 do not access the passed smart pointer itself at the same time, only the CMeef object), you don't need to worry about synchronizing the smart pointer's copy constructors/assignment operators.