Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread safety for overloaded operator new

Though standard doesn't guarantee the thread-safety for new, most of the multi-threading operating systems support thread-safe operator new.

I am implementing my own memory management for the dynamic allocation of certain class (say MyClass) in my code. For thread safety of MyClass, I may have to use pthread or boost:: library.

I thought that if new is already thread safe then I can overload that for MyClass and leverage its safety without worrying about using those libraries.

class MyClass {
// data
public:
  void* operator new (size_t);
  void operator delete (void*);
};

Is it a fair assumption for C++03 systems/compilers?

Edit: Since my question is not followed by few users. I am detailing that part:

If I have 2 threads which do new int() and new int(), then 2 unique memory addresses will be returned. Now, in my overloaded MyClass::new I am not using global ::new() or any threading library; but own memory manager (which doesn't know anything about threads). Pseudo code:

char pool[BIG_SIZE];
void* MyClass::operator new (size_t size)
{
  // get some memory from 'pool' without using any thread library
  return p;
}

My assumption is, since global ::new is thread safe, this overloaded operator new also should be thread-safe. In other words, compiler should be emitting thread-safety related code wherever it encounters new keyword. Is this a correct assumption ?

like image 654
iammilind Avatar asked Oct 12 '11 11:10

iammilind


People also ask

Is new operator thread safe?

The C++ new and delete operators are thread safe, but this means that a thread may have to wait for a lock on these operations. Once memory is obtained for a thread, the thread_alloc memory allocator keeps that memory available for the thread so that it can be re-used without waiting for a lock.

Is CPP thread safe?

It's safe to read and write to one instance of a type even if another thread is reading or writing to a different instance of the same type.

When should I worry about thread safety?

Thread safety becomes a concern if there is at least a single entry point which can be accessed by multiple threads. If a piece of code is accessed by multiple threads and is calling other method/class/etc., then all this code tree becomes vulnerable.

What are the restrictions of operator overloading?

1) Only built-in operators can be overloaded. New operators can not be created. 2) Arity of the operators cannot be changed. 3) Precedence and associativity of the operators cannot be changed.


2 Answers

It is.

However note that in C++11 new is thread safe.

Of course, when you add thread unsafe code, it makes your operator new thread unsafe.

Following your edit (which changed the whole question):

The assumption that the compiler adds thread safety code around the new call is pretty wrong. Sane implementations will always add thread safety within the inner implementation of operator new (already because of efficiency considerations like per-thread memory pools).

That is, when you write a thread unsafe allocation function, just by naming it operator new will not magically make it thread safe, as this is just like any other function, only with a special way to be invoked.

like image 190
PlasmaHH Avatar answered Nov 07 '22 23:11

PlasmaHH


I think with your edited question, the answer is a definite "No".

You also seem to be confused about new operators and new expressions (there's no such thing as ::new(), there's only ::new and ::operator new()), so perhaps it's best to break this down.

When you write T * p = new T;, where T has an overloaded operator-new, then a sequence equivalent to the following happens:

void * addr = T::operator new(sizeof(T));  // #1
::new (addr) T;                            // global placement-new

The function call in #1 is what matters. Is this call thread-safe? Well, that's entirely up to how you define that function! There is nothing in the standard that guarantees any particular behaviour of that function, which is after all an entirely ordinary function.

The only thing that the (new) standard, or the compiler vendor, does guarantee is that the default-provided global function void * ::operator new(std::size_t) throw(std::bad_alloc); is thread-safe. So if you write your own function using that one, you're OK; otherwise you're on your own:

struct Foo
{
  static void * operator new(size_t n) { return ::operator new(n); } // OK
};

struct Bar
{
  static void * operator new(size_t n) { horribly_broken_function(); return 0x0505; }
  // probably not OK
}
like image 22
Kerrek SB Avatar answered Nov 08 '22 00:11

Kerrek SB