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 ?
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.
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.
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.
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.
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.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With