5

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 ?

Community
  • 1
  • 1
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 3
    `MyClass::operator new` is just a regular function with somewhat weird syntax. It is not related to any `::operator new` variant and does not magically inherit their thread safety. – n. m. could be an AI Oct 12 '11 at 11:24
  • 1
    As you already stated most compilers do provide a thread safe version of new eventhough the C++03 standard does not gaurantee the same.So what is the Q? You will need to rely on the documentation of the compiler you are targetting, If you mean from portability perspective, since standard doesn't explicitly demand new to be thread safe, strictly its not 100% portable, but its still a fair assumption, given that most compilers implement it. – Alok Save Oct 12 '11 at 11:26
  • @Als, In a given platform if `new` is thread safe, then is it fair to assume that its overloaded version(for certain `class`) **also** be thread safe ? – iammilind Oct 12 '11 at 11:29
  • That solely depends on the code that you write while overloading the new. Actually, this holds good for any thread safe api/construct.The api or constructs are themselves thread safe but no implementation can gaurantee them to be thread safe if their usage is not done in a thread safe manner. – Alok Save Oct 12 '11 at 11:33

3 Answers3

5

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.

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57
  • I am not getting your answer. Whether C++03 **overloaded** `operator new` thread safe or not ? – iammilind Oct 12 '11 at 11:20
  • @iammilind: See the first two words. It is. Or in other words: There is nothing inherently thread unsafe there. But since you overload it, you write code in it. That code could do something that is not thread safe, which would then make your whole operator new not thread safe. But as long as you only do thread safe things, it will stay thread safe. – PlasmaHH Oct 12 '11 at 11:28
  • Like n.m. above, I don't follow your question -- the overloaded operator is just a perfectly ordinary (static) member function. It is as good or as bad as you make it! If the memory acquisition inside your operator uses `::operator new(n);`, then that particular call is thread-safe, and you have to make everything else thread-safe, too. – Kerrek SB Oct 12 '11 at 11:51
2

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
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

From the updated question:

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 ?

No.

Or, yes in the trite sense that it matters to all code the compiler generates, namely that the compiler isn't allowed to introduce data races that weren't there in the original source code (in principle, the previous wording is found in the C++11 memory model, but in practice C++98 compilers supporting threads follow it anyway because otherwise it would be impossible to create robust threaded programs).

IOW, the compiler helps you create thread-safe code to the extent that it won't make thread-safe code that you write thread-unsafe. However, it doesn't go the other way; there is no magic thread-safety pixie dust that the compiler can sprinkle over your thread-unsafe code to make it thread-safe.

Another explanation specifically wrt. operator new copy-pasted from the comment by "n.m":

MyClass::operator new is just a regular function with somewhat weird syntax. It is not related to any ::operator new variant and does not magically inherit their thread safety

or the same thing from "Kerrek SB":

Like n.m. above, I don't follow your question -- the overloaded operator is just a perfectly ordinary (static) member function. It is as good or as bad as you make it! If the memory acquisition inside your operator uses ::operator new(n);, then that particular call is thread-safe, and you have to make everything else thread-safe, too

Truth to be told, I'm having trouble figuring out what is still unclear here..

janneb
  • 36,249
  • 2
  • 81
  • 97