4

I wanted to try out TBB's scalable_allocator, but was confused when I had to replace some of my code. This is how allocation is done with the allocator:

SomeClass* s = scalable_allocator<SomeClass>().allocate( sizeof(SomeClass) );

EDIT: What's shown above is not how allocation is done with scalable_allocator. As ymett correctly mentioned, allocation is done like this:

int numberOfObjectsToAllocateFor = 1;
SomeClass* s = scalable_allocator<SomeClass>().allocate( numberOfObjectsToAllocateFor );
scalable_allocator<SomeClass>().construct( s, SomeClass());
scalable_allocator<SomeClass>().destroy(s);
scalable_allocator<SomeClass>().deallocate(s, numberOfObjectsToAllocateFor);

It's pretty much like using a malloc:

SomeClass* s = (SomeClass*) malloc (sizeof(SomeClass));

This is the code I wanted to replace:

SomeClass* SomeClass::Clone() const
{
   return new SomeClass(*this);
}//Clone

So tried a program:

#include<iostream>
#include<cstdlib>
using namespace std;

class S
{
        public:
        int i;
        S() {cout<<"constructed"<<endl;}
        ~S() {cout<<"destructed"<<endl;}
        S(const S& s):i(s.i) {}
};

int main()
{
        S* s = (S*) malloc(sizeof(S));
        s = (S*) S();//this is obviously wrong
        free(s);
}

and here I found that calling malloc does not instantiate the object (I've never used malloc earlier). So before figuring out how to pass *this to the copy ctor, I'd like to know how to instantiate the object when working with malloc.

Community
  • 1
  • 1
Nav
  • 19,885
  • 27
  • 92
  • 135
  • http://stackoverflow.com/questions/222557/cs-placement-new – etarion Feb 10 '11 at 11:09
  • Why won't you override `operator new` either for the class you're interested in or just the global one? – sharptooth Feb 10 '11 at 11:10
  • @sharptooth: That's a nice idea, but for now, I'm just testing to see if scalable_allocator really helps in avoiding heap contention. Overriding new will definitely come handy if the tests are successful. Thanks :) – Nav Feb 10 '11 at 11:17
  • If the allocator is standard-compliant, it should have the construct and destroy method: http://www.cplusplus.com/reference/std/memory/allocator/construct/ – visitor Feb 10 '11 at 11:18
  • Overriding `operator new()` is much faster and more reliable - you just do that and recompile and see if it helps, you don't need to change the calling code - it will come into effect everywhere immediately. – sharptooth Feb 10 '11 at 11:25

3 Answers3

22

You'll need to use placement new after getting the raw memory from malloc.

void* mem = malloc(sizeof(S));
S* s = new (mem) S(); //this is the so called "placement new"

When you're done with the object you have to make sure to explicitly call its destructor.

s->~S();
free(mem);
manneorama
  • 1,291
  • 12
  • 22
  • Thanks. It seemed counterintuitive to use 'new' when the whole purpose of using TBB's scalable_allocator was to replace new. But I guess it's different because it's placement new that's being used. – Nav Feb 10 '11 at 11:16
9

Use placement new

#include <memory>
//...
int main()
{
        S* s = (S*) malloc(sizeof(S));
        s = new (s) S();//placement new
        //...
        s->~S();
        free(s);
}
Community
  • 1
  • 1
KitsuneYMG
  • 12,753
  • 4
  • 37
  • 58
0

The parameter to allocate() is the number of objects, not the size in bytes. You then call the allocator's construct() function to construct the object.

scalable_allocator<SomeClass> sa;
SomeClass* s = sa.allocate(1);
sa.construct(s, SomeClass());
// ...
sa.destroy(s);
sa.deallocate(s);

If want to use it with a standard library container or other std allocator aware type, simply give it the allocator type.

std::vector<SomeClass, scalable_allocator<SomeClass>> v;
ymett
  • 2,425
  • 14
  • 22
  • I disagree. construct() is used for the placement new functionality. I had taken the syntax of allocate() from one of the examples supplied in TBB. But since you posted this, I'm intrigued. I'll check and get back to you. Thanks :) – Nav Feb 10 '11 at 14:36
  • Oh my! You're right! Thank's a zillion for correcting me! It's sad this website does not have the option of voting up an answer more than once. I'd have voted it up a hundred times! One question: In the line sa.construct(s, SomeClass()); , is a temporary object of SomeClass() getting created? Also, I don't get the point of allocating for n objects. If I had done sa.allocate(2); then would I have to construct two objects using sa.construct(s, SomeClass()); ? p.s: could you edit your answer a bit? SO isn't allowing me to vote up your answer saying that you need to edit it. – Nav Feb 10 '11 at 14:57
  • Edited my question to include a corrected version of the code. Thank you so much! The output to my program is now `constructed destructed destructed`. The first 'destructed' happens immediately after/during the construct() function. Wonder why. – Nav Feb 11 '11 at 06:25