2

I am currently working on a class assignment where I need to implement a lock-free linked list. The structure of each of my nodes is essentially:

class Node {
    std::shared_ptr<Node> next;
    long long             key;
}

I need to somehow embed an extra bit of data into the "next" pointer. I cannot use an extra boolean field, because the "next" pointer needs to be updated atomically using compare_exchange_strong(). I also have to use a std::shared_ptr for its garbage collection abilities; performing memory reclamation on a lock-free data structure is beyond the scope of what we have studied in the course so far.

If I were using a plain old pointer, I could use bit manipulation operators to "twiddle" the high bit of the pointer, but clearly this won't work, because once I twiddle the bit, the pointer points to an invalid memory location, and when the assignment operator attempts to access the control block, it will cause a segmentation violation.

Can anyone offer any insights on how I can accomplish this?

Oh, and for those who are curious, I am using g++-4.8.2 on a Linux system.

dyp
  • 38,334
  • 13
  • 112
  • 177
Ken P
  • 552
  • 3
  • 11
  • 2
    You could embed information in a custom deleter. – dyp Nov 15 '13 at 17:58
  • Do you know where I could find an example of something like this? – Ken P Nov 15 '13 at 18:06
  • 1
    @DyP The deleter is per pointed-to-object, not per-shared-pointer, so I guess this is quite different. – Daniel Frey Nov 15 '13 at 18:07
  • @DanielFrey: But that custom deleter could certainly strip off that extra bit which is causing problems. The main problem I see is that the "twiddled" pointer is likely to get its own independent reference count. – MSalters Nov 15 '13 at 18:15
  • @MSalters You can share ownership of two unrelated pointers. – dyp Nov 15 '13 at 18:24
  • 1
    it's not clear to me how you're using `compare_exchange_strong` with `shared_ptr` – Sam Miller Nov 15 '13 at 18:27
  • @SamMiller There's a special overload for [`compare_exchange_strong`](http://en.cppreference.com/w/cpp/memory/shared_ptr/atomic) that takes two raw pointers to `shared_ptr` and a `shared_ptr` by value. – dyp Nov 15 '13 at 18:31

1 Answers1

0

Seems like you are trying to mix two different things here.

Meddling with the pointer in a shared_ptr does not strike me as a good idea. The shared pointer is thread safe, but you can accomplish that yourself if you are using atomic operations.

Anyway, a custom deleter as suggested before is done like this;

struct d { void operator()(foo* f){ delete f; } };

...and you create a shared_ptr w/this using;

shared_ptr<bar> b(new bar, d());

...but why not use atomic operations to start with?

Cheers!

Daniel
  • 24
  • 5
  • I wanted to use shared_pointers for their memory management benefits; you don't have to worry about when to delete them. However, apparently in gcc-4.8.2 they aren't 100% thread-safe; in one of my implementations, I was getting really weird "calling a pure virtual function" errors. I ended up writing my own memory manager that used hazard pointers to determine when it was safe to reuse a data element. I also had to write a lock-based approach as well, and the custom memory manager was about 300-400% faster than using the shared pointers... – Ken P Dec 11 '13 at 21:43
  • Regarding the "pure virtual function" errors; I get that sometimes when I call a virtual function from a base class destructor. Sometimes I put a `cout << "Destroying: " << *this` in the destructor for logging reasons and if the `operator<<` contains virtual function calls... :/ – Daniel Jan 10 '14 at 13:11