Threaded SmartPtr questions

D

dbtouch

Dear C++ Users,

I am studying Modern C++ design and I simplified a threaded smart
pointer implementation as following code. As I execute it I found that
tsp is actually deleted twice. I am trying to see whether my approach
is correct and would like to hear your opinions.

dbtouch

#include <iostream>

class Foo {
public:
void func() {
std::cout << "Foo::func()" << std::endl;
}

Foo(const Foo& f) {
std::cout << "Foo::Foo(const Foo&)" << std::endl;
}

Foo() {
std::cout << "Foo::Foo()" << std::endl;
}

~Foo() {
std::cout << "Foo:~Foo()" << std::endl;
}
};

class Mutex {
public:
void acquire() {
std::cout << "Mutex.acquire()" << std::endl;
}
void release() {
std::cout << "Mutex.release()" << std::endl;
}
};

template <typename SharedObject, typename SyncPolicy>
class ThreadedSmartPtr {
SharedObject* m_ptr;
Mutex lock;

public:
ThreadedSmartPtr(SharedObject* ptr, SyncPolicy& lck) :
m_ptr(ptr), lock(lck) {
lock.acquire();
}

~ThreadedSmartPtr() {
lock.release();
}

SharedObject* operator -> () {
return m_ptr;
}
};

template <typename T>
class SmartPtr {
T *object;

public:
SmartPtr(T* value) : object(value) {
}

T operator->() {
return *object;
}

~SmartPtr() {
if (object)
delete object;
}
};

typedef ThreadedSmartPtr<Foo, Mutex> oldSmartPtr;

int main() {
Foo *ptr = new Foo;
Mutex m;
oldSmartPtr tsp(ptr, m);

SmartPtr<oldSmartPtr> sp(&tsp);
sp->func();
}
 
J

James Kanze

I am studying Modern C++ design

I'm not sure of your level, but from what I've seen and heard of
it, I don't think it's exactly for beginners in C++.
and I simplified a threaded
smart pointer implementation as following code. As I execute
it I found that tsp is actually deleted twice. I am trying to
see whether my approach is correct and would like to hear your
opinions.

There are at least two serious problems with your code.
#include <iostream>
class Foo {
public:
void func() {
std::cout << "Foo::func()" << std::endl;
}
Foo(const Foo& f) {
std::cout << "Foo::Foo(const Foo&)" << std::endl;
}
Foo() {
std::cout << "Foo::Foo()" << std::endl;
}
~Foo() {
std::cout << "Foo:~Foo()" << std::endl;
}
};
class Mutex {

Not important in your example, but a real Mutex will have
identity. Which means that it won't support copy nor
assignment. Whatever you end up designing, you must take this
into account.
public:
void acquire() {
std::cout << "Mutex.acquire()" << std::endl;
}
void release() {
std::cout << "Mutex.release()" << std::endl;
}
};
template <typename SharedObject, typename SyncPolicy>
class ThreadedSmartPtr {
SharedObject* m_ptr;
Mutex lock;

If Mutex isn't copiable, nor is your ThreadedSmartPtr. (That
may or may not be a problem. The smart pointers I've seen which
manage locks all use reference counting to support copy.)

And of course, since the mutex is only known to the single
instance, there's no way it can protect anything not using the
particular instance.
public:
ThreadedSmartPtr(SharedObject* ptr, SyncPolicy& lck) :
m_ptr(ptr), lock(lck) {
lock.acquire();
}
~ThreadedSmartPtr() {
lock.release();
}
SharedObject* operator -> () {
return m_ptr;
}
};
template <typename T>
class SmartPtr {
T *object;
public:
SmartPtr(T* value) : object(value) {
}
T operator->() {
return *object;
}
~SmartPtr() {
if (object)
delete object;
}
};
typedef ThreadedSmartPtr<Foo, Mutex> oldSmartPtr;
int main() {
Foo *ptr = new Foo;
Mutex m;
oldSmartPtr tsp(ptr, m);
SmartPtr<oldSmartPtr> sp(&tsp);

And this will result in undefined behavior. As written, your
SmartPtr can only be initialized with dynamically allocated
objects.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top