Boost logo

Boost Users :

Subject: [Boost-users] [thread] thread_specific_ptr is not initialized with NULL
From: Michael Gopshtein (mgopshtein_at_[hidden])
Date: 2009-06-07 13:58:37


Hi,

As I understand from documentation, once thread_specific_ptr is created,
first call to get() should return NULL in all threads. Actually sometimes it
doesn't happen. Consider the following scenario:

1) thread T1 initializes some global tss object (by doing "new" on global
thread_specific_ptr<>*)
2) thread T2 tries to read the value with get(), and gets null. It sets a
correct value (unsigned int 42)
3) thread T1 deletes tss object, and allocates a new one instead.
4) thread T2 tries to read the value from the new object

So I expected that in (4) thread T2 will get NULL again. Actually, when new
object created in (3) is created in same memory location, T2 gets the
original value in (4), and not NULL. When new pointer allocated in (3) is
different, T2 gets NULL as expected (verified using "placement new" to
control location of the tss object).

Is it a bug or inpropriate use pattern?

The code that demonstrates the issue is listed below (please ignore
synchronization issues) - note the line with a comment: when I do "new
(buf2) ..." instead, it works as expected.

Thanks,
Michael

======================================
#include <boost/thread/tss.hpp>
#include <boost/thread.hpp>
#include <unistd.h>
#include <iostream>
using namespace std;

boost::thread_specific_ptr<unsigned long> *pptr = NULL;
char buf1[sizeof(boost::thread_specific_ptr<unsigned long>)];
char buf2[sizeof(boost::thread_specific_ptr<unsigned long>)];

void do1() {
 cout << "Creating TLS index\n";
 pptr = new (buf1) boost::thread_specific_ptr<unsigned long>;
 sleep(5);

 cout << "Replacing TLD index\n";
 pptr->~thread_specific_ptr();
 pptr = new (buf1) boost::thread_specific_ptr<unsigned long>; // HERE WE
CAN ALLOCATE IN buf1 OR buf2
}

void printval() {
 unsigned long * val = pptr->get();
 if (val == NULL) {
  cout << "Got NULL value\n";
  val = new unsigned long(42);
  pptr->reset(val);
 } else {
  cout << "Got value: " << *val << endl;
 }
}

void do2() {
 for (int i = 0; i < 4; i++) {
  sleep(2);
  printval();
 }
}

int main(int argc, char *argv[]) {
 cout << "size " << sizeof(boost::thread_specific_ptr<unsigned long>) <<
endl;

 boost::thread t1(do1);
 boost::thread t2(do2);

 t1.join();
 t2.join();

 return 0;
}
============================
OUTPUT:
Creating TLS index
Got NULL value
Got value: 42
Replacing TLD index
Got value: 42
Got value: 42


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net