venkysmarty
venkysmarty

Reputation: 11431

singleton usage in multithread

I am reading a book on applied C++ about locking and design.

void addRef() { ref++; }
void subRef() { if(--ref == 0) delete this; }

Although a statement like ref++ looks trivial, there is no guarantee that it is atomic. But before you go and rewrite this code to add locking, you need to know how your application will use it. In this particular example, a bug is created if addRef is called after subRef. The problem is not with missing locks, it is poor design. If an object must persist beyond scope of a thread, it should be created and owned by a different thread that will not go out of scope.

My question on above text is

  1. What does author mean by poor design and how this is avoided by "If an object must persist beyond scope of a thread, it should be created and owned by a different thread that will not go out of scope." ? Request to give an example on this.

Upvotes: 0

Views: 114

Answers (3)

James Kanze
James Kanze

Reputation: 153919

Who knows? You'd have to ask the author. This looks like classical reference counting to me: to make it safe, you'd have to either user a mutex to protect all accesses to ref, or make ref some sort of atomic variable. (C++11 has a whole range of functions on std::atomic<int> which you can use.)

With regards to the quoted text: you can make anything unsafe if you don't use it right. If two threads are accessing the same instance, then ref should already be at least 2, so that if one thread drops the reference, the object will still continue to exist. There is no need for any additional thread to complicate matters.

Upvotes: 0

Dariusz
Dariusz

Reputation: 22251

void thread1work(RefCntObj* refcntObj) 
{
  refcntObj.addRef();
  // any work
  refcntObj.subRef();
}

int main(void) {
  RefCntObj* refcntObj= new RefCntObj(); // I assume the constructor calls addRef()
  std::thread t(thread1work, std::ref(f));
  refcntObj->subRef(); // may be called after thread1Work or before it
}

There is no guarantee that the thread1work will be called before main's refcntObj->subRef();. In such case the object would already be deleted and the pointer invalid.

Upvotes: 1

ClaireG
ClaireG

Reputation: 1244

By poor design of code, the author means a poor construction of classes and methods ; where you place what and how that position makes your code accessible.

"If an object must persist beyond scope of a thread, it should be created and owned by a different thread that will not go out of scope."

Simply put, the above means that if you have B inside of A(Thread) but you need to use B also in C, than you must remove B from inside the thread(A) and make it independent from it, so you can use it in both A and C.

Upvotes: 0

Related Questions