Jump to content
  • Advertisement
Sign in to follow this  
ndwork

Global Placement New With Alignment

This topic is 3606 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Thank you (anyone) for helping me out. I am coding in C++. This is my issue. I have a templated container class - it is essentially an array of the templated parameter. I would like the user to be able to pass in a construction argument that allows him/her to specify whether or not the memory that the class allocates is aligned. So I have code that looks like this: typedef enum{ ALIGN_THIS = 0 } ACV_INTERNAL_ENUM; void* operator new[]( std::size_t size, std::size_t alignment, ACV_INTERNAL_ENUM acvEnum ) throw(std::bad_alloc){ if( size==0 ) size=1; void* pMem = _aligned_malloc( size, alignment ); if(pMem) return pMem else throw std::bad_alloc(); } void operator delete[]( void* pMem, std::size_t alignment, ACV_INTERNAL_ENUM acvEnum ) throw(){ _aligned_free( pMem ); } template <class T> myClass<T>::myClass( std::size_t nElements, bool iShouldAlign ){ if( iShouldAlign ){ m_data = new( 16, ALIGN_THIS ) T [nElements]; // Call my overloaded new } else { m_data = new T[nElements]; // Call regular new } } I have overloaded the new operator with the unused parameter 'acvEnum' to be able to specify when to use this version of operator new without overriding a standard version of new. I am failing at creating the destructor for myClass. The problem is that one cannot specifically call the corresponding overloaded delete. I need to call _aligned_free to correspond with _aligned_malloc, so the default version of delete will not work. The templated parameter T can be a primitive type, so it doesn't necessarily have a destructor; nor can I create a class that inherits from T. Any suggestions and thoughts would be greatly appreciated. Again, thank you all for your help. [Edited by - ndwork on December 3, 2008 1:02:55 PM]

Share this post


Link to post
Share on other sites
Advertisement
Could you maybe create an allocator/deallocator functor and make it one of the template parameters.

STL containers can use custom allocators, I believe, to do things like the this,
maybe it would be possible to write a custom allocator for say a std::vector<T> to do what you want but its something i have very little knowledge of.

Just throwing out suggestions :)

EDIT: you would have to make the functor a template class i'd think, template template, yummy :p

Share this post


Link to post
Share on other sites
Don't know about the rest (is it absolutely necessary to overload new and delete?), but

Quote:

The templated parameter T can be a primitive type, so it doesn't necessarily have a destructor


This is not 100% true. This should be entirely valid:

#include <memory>
template <class T>
void foo()
{
char* buf = new char[sizeof(T)];
T* p = new(buf) T;
//...
p->~T();
delete buf;
}

int main()
{
foo<int>();
}

Share this post


Link to post
Share on other sites
Thank you very much for your reply - you are indeed correct. Primitive types do have destructors (or effectively have destructors).

The solution that I've come up with is as follows:


typedef enum{ ALIGN_THIS=0 } ACV_INTERNAL_ENUM;

void* operator new[]( std::size_t size, std::size_t alignment, ACV_INTERNAL_ENUM acvEnum ) throw(std::bad_alloc){
void* pMem = _aligned_malloc( size, alignment );
if(pMem) return pMem
else throw std::bad_alloc();
}
// Note: this is an incomplete overload of new. It was made simple for
// the purpose of this post.


void operator delete[]( void* pMem, std::size_t alignment, ACV_INTERNAL_ENUM acvEnum ) throw(){
_aligned_free( pMem );
}

template <class T>
void myDeallocate( T* ptr, const int &numElements ){
for( int i=0; i<numElements; ++i ) ptr.~T();
_aligned_free( ptr );
}


//The class then allocates the memory using the overloaded new, and deallocates the memory using the function myDeallocate. Like this:


int main(){
p* = new( 16, ALIGN_THIS ) T [18];
// ...
myDeallocate( p, 18 );
}


This make the cardinal mistake of mixing new with free, but I don't see another way to solve the problem. Does anyone see a problem with the implementation the way I have it?



Share this post


Link to post
Share on other sites
It looks like you could have something like this:


template <class T, unsigned Alignment>
class AlignedAllocator
{
public:
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template <class U>
struct rebind
{
typedef AlignedAllocator<T, Alignment> other;
};
pointer address(reference r)
{
return &r;
}
const_pointer address(const_reference r)
{
return &r;
}
size_type max_size()
{
return std::numeric_limits<size_type>::max();
}
void construct(const pointer ptr, const value_type& val)
{
new (ptr) T(val);
}
void destroy(const pointer ptr)
{
ptr->T::~T();
}
pointer allocate(const size_type n)
{
return (pointer)_aligned_malloc(n * sizeof(T), Alignment);
}
pointer allocate(const size_type n, const void * const)
{
return allocate(n);
}
void deallocate(pointer p, size_type )
{
_aligned_free(p);
}
bool operator==(const AlignedAllocator &) const
{
return true;
}
bool operator!=(const AlignedAllocator &) const
{
return false;
}
};



And then simply use it with the STL, e.g:


std::vector<int, AlignedAllocator<int, 16> > vec;

Share this post


Link to post
Share on other sites
Don't want to hijack the OP's thread, but visitor what is the following for:


template <class U>
struct rebind
{
typedef AlignedAllocator<T, Alignment> other;
};




I'm glad you posted an allocator my c++ book says its too advanced a topic for it :|

Share this post


Link to post
Share on other sites
I actually ripped most of the code from boost allocators / standard draft :) This is supposed to be some sort of "template typedef", which probably might or might not get used somewhere for some purpose.

Quote:

3 The template class member rebind in the table above is effectively a
template typedef: if the name Allocator is bound to SomeAllocator<T>,
then Allocator::rebind<X>::other is the same type as SomeAllocator<X>.


Actually I suspect it should be:


template <class U>
struct rebind
{
typedef AlignedAllocator<U, Alignment> other;
};


Share this post


Link to post
Share on other sites
Cool thanks, I really want to look into allocators more. The comparison operators seem alittle pointless though :p

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!