Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Memory allocators

isnork
Beginner
305 Views
Hello everyone!

I was playing around whith the memory allocators provided by the library in order to understand better how to work with them. This is what I did:
[bash]class Number {
    private:
      int n;
    public:
      Number(): n(9){};
      Number( const int& i): n(i){};
      const int Num(void) const { return n; }
      void SetNum(int i) { n = i; }
};

static Number* AllocateNumber( const int n ) {
  Numero* num = (Number*)tbb::tbb_allocator().allocate(sizeof(Number)+n);
  num->SetNum( n );
  return num;
};

static void DeallocateNumber( Number* n ) {
  tbb::tbb_allocator().deallocate((int*)n,n->Num());
};

int main(){
  Number* one = AllocateNumber( 1 );
  // more things
  DeallocateNumber( one );
}[/bash]
This works fine(I think) but then I tried this other thing:
[bash]class Real {
    private:
      int n;
      double r;
    public:
      Real(): n(9),r(500.50){};
      Real( const int& i, const double& j ): n(i),r(j){};
      const int Num(void) const { return n; }
      const double Real(void) const { return r; }
      void SetNum(int i) { n = i; }
      void SetReal(double j) {r = j; }
};

static Real* AllocateReal( const int n, const double r ) {
 Real* num = (Real*) tbb::tbb_allocator().allocate(sizeof(Real)+n+r);
 num->SetNum(n);
 num->SetReal;
 return num;
}[/bash]
This fails since I'm passing two arguments to the allocator template. So my question is, how can I allocate a Real object with two data members( an int and a double)? Is something like the first AllocateNumber or a workaround is needed?

Thanks!
0 Kudos
1 Solution
RafSchietekat
Valued Contributor III
305 Views
Please have a good look at the documentation to see what arguments to pass to allocate() (ignore "hint") and deallocate() (tbb::tbb_allocator is modeled after std::allocator, so you could also look there).

As with std::allocator, tbb_allocator::allocate() returns a region of memory sufficient to hold a specified number of the specified type of objects, but does not initialise it in any way. You may use tbb_allocator::construct(), or std::raw_storage_iterator, or std::uninitialized_copy, or std::uninitialized_fill, or std::uninitialized_fill_n, or any other way to place values there, unless you know that the object can be safely assigned, which seems to be the case here even with the nontrivial constructors. Similarly for deallocation.

View solution in original post

0 Kudos
3 Replies
isnork
Beginner
305 Views
Hello again.

I tried this:
[cpp]static Real* AllocateReal( const int n, const double r ) {
double n_ = (double) n;
Real* num = (Real*) tbb::tbb_allocator().allocate(sizeof(Real)+n_+r);
num->SetNum(n);
num->SetReal;
}

static void DeallocateReal( Real* n) {
tbb::tbb_allocator().deallocate((double*)n,n->Num());
tbb::tbb_allocator().deallocate((double*)n,n->Real());
}

int main(){
Real* r = AllocateReal( 7, 8.5 );
std::cout << r->Num() << " & " << r->Real() << "n";
DeallocateReal( r );
}[/cpp]
It compiles( with warnings ) and it works.
The warnings:

In function Real* AllocateReal(int, double):
var.cpp:54: warning: passing double for argument 1 to typename tbb::internal::allocator_type::value_type* tbb::tbb_allocator::allocate(size_t, const void*) [with T = double]
var.cpp: In function void DeallocateReal(Real*):
var.cpp:61: warning: passing double for argument 2 to void tbb::tbb_allocator::deallocate(typename tbb::internal::allocator_type::value_type*, size_t) [with T = double]

Is there any way to get rid of the warnings? And, am I doing this properly or is there a better way to allocate/deallocate the objects?

Thanks!
0 Kudos
RafSchietekat
Valued Contributor III
306 Views
Please have a good look at the documentation to see what arguments to pass to allocate() (ignore "hint") and deallocate() (tbb::tbb_allocator is modeled after std::allocator, so you could also look there).

As with std::allocator, tbb_allocator::allocate() returns a region of memory sufficient to hold a specified number of the specified type of objects, but does not initialise it in any way. You may use tbb_allocator::construct(), or std::raw_storage_iterator, or std::uninitialized_copy, or std::uninitialized_fill, or std::uninitialized_fill_n, or any other way to place values there, unless you know that the object can be safely assigned, which seems to be the case here even with the nontrivial constructors. Similarly for deallocation.
0 Kudos
isnork
Beginner
305 Views
Thanks Raf!
Solved!
0 Kudos
Reply