Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning pointers in a thread-safe way

Assume I have a thread-safe collection of Things (call it a ThingList), and I want to add the following function.

Thing * ThingList::findByName(string name)
{
  return &item[name]; // or something similar..
}

But by doing this, I've delegated the responsibility for thread safety to the calling code, which would have to do something like this:

try 
{
  list.lock(); // NEEDED FOR THREAD SAFETY
  Thing *foo = list.findByName("wibble");
  foo->Bar = 123;
  list.unlock();  
}
catch (...) 
{
  list.unlock();
  throw;
} 

Obviously a RAII lock/unlock object would simplify/remove the try/catch/unlocks, but it's still easy for the caller to forget.

There are a few alternatives I've looked at:

  • Return Thing by value, instead of a pointer - fine unless you need to modify the Thing
  • Add function ThingList::setItemBar(string name, int value) - fine, but these tend to proliferate
  • Return a pointerlike object which locks the list on creation and unlocks it again on destruction. Not sure if this is good/bad practice...

What's the right approach to dealing with this?

like image 883
Roddy Avatar asked Apr 19 '10 21:04

Roddy


People also ask

Are pointers thread-safe?

Yes, the control block is thread-safe; but no, the access to the resource is not thread-safe. That means, modifying the reference counter is an atomic operation and you have the guarantee that the resource will be deleted exactly once. These are all guarantees a std::shared_ptr gives you.

How do you return the value of a pointer?

To get the value pointed to by a pointer, you need to use the dereferencing operator * (e.g., if pNumber is a int pointer, *pNumber returns the value pointed to by pNumber . It is called dereferencing or indirection).

What is returning pointer?

Return Function Pointer From Function: To return a function pointer from a function, the return type of function should be a pointer to another function. But the compiler doesn't accept such a return type for a function, so we need to define a type that represents that particular function pointer.

Can we return pointer to a local variable?

We can pass pointers to the function as well as return pointer from a function. But it is not recommended to return the address of a local variable outside the function as it goes out of scope after function returns.


2 Answers

There is no one "right approach"; it depends on the needs of your application.

If at all possible, return things by value, or return a copy that the caller can do whatever they want with.

A variant of the above is to return a modifiable copy, and then provide a way to atomically merge a modified object back into the list. Something like:

Thing t = myThingList.getThing(key);
t.setFoo(f);
t.setBar(b);
myThingList.merge(t);     // ThingList atomically updates the appropriate element

However, that can cause problems if multiple threads try to update the same object.

The "pointerlike object" idea sounds cool, but I suspect it would lead to hard-to-find bugs when some lock isn't getting released somewhere.

I'd try to keep all the locking/unlocking code within ThingList, so the ThingList::set... functions are probably what I would do.

like image 103
Kristopher Johnson Avatar answered Oct 11 '22 17:10

Kristopher Johnson


store and return boost::shared_ptr s

you have to lock during access but you are safe after the unlock

like image 25
pm100 Avatar answered Oct 11 '22 16:10

pm100