By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,194 Members | 829 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,194 IT Pros & Developers. It's quick & easy.

Allocation schema w.r.t. padding and alignment...

P: n/a
I am thinking of porting a library from C to C++, and was tinkering with
ways to ensure proper struct padding and alignment. The library is very
hardware specific, and will simply crash and/or perform bad if the memory
some of its algos use is not properly padded and aligned. So I had to come
up with a way to create several objects of the same class that have
different alignment and padding...

Consider my temporary solution, using placement new and templates:
Example.cpp
( compiles with GCC and MSVC++6.0 )
-----------------

// C++ code created by C programmer!

#include <iostream>
#include <cassert>
#include <cstddef>
#include <new>
#define AC_CACHE_LINE 128
#define AC_ALGO1_ALIGN ( AC_CACHE_LINE / 2 )
#define AC_ALGO2_ALIGN ( AC_CACHE_LINE * 2 )
template< size_t T_Align >
struct TExampleImpl_Padded
{
// snip

int m_iExampleState;

// Is this legal!?! Works for GCC... humm
char PAD1[T_Align - sizeof( int )];
};
struct SExampleImpl
{
int m_iExampleState;
};
template< typename T_Impl, size_t T_Align /* snip */ >
class TExample
{

public:

TExample() : m_pImpl( 0 ), m_pImplMem( 0 )
{
// Assert
if ( ! T_Align ||
T_Align != 1 && ( ((ptrdiff_t)m_pImpl) % sizeof( size_t ) ) )
{
throw;
}

// Alloc and align
m_pImplMem = ::operator new( sizeof( T_Impl ) + ( T_Align - 1 ) );

m_pImpl = new ( (void*)(( (((ptrdiff_t)m_pImplMem) + (T_Align - 1))
& -(T_Align) )) ) T_Impl;

// Assert
if ( T_Align != 1 && ( ((ptrdiff_t)m_pImpl) % T_Align ) )
{
m_pImpl->~T_Impl();
::operator delete( m_pImplMem );

throw;
}

std::cout << m_pImpl << "::sizeof - " << sizeof( *m_pImpl ) <<
std::endl;

// Init impl
m_pImpl->m_iExampleState = 0;
}

~TExample()
{
assert( m_pImpl && m_pImplMem );

// Dtor, placement new...
m_pImpl->~T_Impl();
::operator delete( m_pImplMem );
}
public:
// snip
private:

T_Impl *m_pImpl;
void *m_pImplMem;
};
// Now I can create a number of different padding and alignments

typedef TExample< TExampleImpl_Padded< AC_CACHE_LINE >, AC_CACHE_LINE >
CExample;
typedef TExample< TExampleImpl_Padded< AC_ALGO1_ALIGN >, AC_ALGO1_ALIGN >
CExampleAlgo1;
typedef TExample< TExampleImpl_Padded< AC_ALGO2_ALIGN >, AC_ALGO2_ALIGN >
CExampleAlgo2;
typedef TExample< SExampleImpl, 1 > CLwExample;


int main()
{
CExample s;
CExampleAlgo1 sa1;
CExampleAlgo2 sa2;
CLwExample lws;

return 0;
}
As you can see, this provides the solution I want, and passes all of the
library's tests, but...

Is this a non-portable crappy solution? If so, got anything better? I'm not
that good at C++, I'm a C guy...

;)

Thank you.
Jul 22 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
> public:

TExample() : m_pImpl( 0 ), m_pImplMem( 0 )
{
DOH!

*************** // Assert
if ( ! T_Align ||
T_Align != 1 && ( ((ptrdiff_t)m_pImpl) % sizeof( size_t ) ) )
{
throw;
} **************

This was not suppose to be pasted in the example!

Sorry.

:O

// Alloc and align
m_pImplMem = ::operator new( sizeof( T_Impl ) + ( T_Align - 1 ) );

m_pImpl = new ( (void*)(( (((ptrdiff_t)m_pImplMem) + (T_Align - 1)) & -(T_Align) )) ) T_Impl;

Jul 22 '05 #2

P: n/a
you know, i use to be such a fan of c++

i think it's the templates that get me down the most...

and to think they've actually brought these over to Java now...

- perry

SenderX wrote:
I am thinking of porting a library from C to C++, and was tinkering with
ways to ensure proper struct padding and alignment. The library is very
hardware specific, and will simply crash and/or perform bad if the memory
some of its algos use is not properly padded and aligned. So I had to come
up with a way to create several objects of the same class that have
different alignment and padding...

Consider my temporary solution, using placement new and templates:
Example.cpp
( compiles with GCC and MSVC++6.0 )
-----------------

// C++ code created by C programmer!

#include <iostream>
#include <cassert>
#include <cstddef>
#include <new>
#define AC_CACHE_LINE 128
#define AC_ALGO1_ALIGN ( AC_CACHE_LINE / 2 )
#define AC_ALGO2_ALIGN ( AC_CACHE_LINE * 2 )
template< size_t T_Align >
struct TExampleImpl_Padded
{
// snip

int m_iExampleState;

// Is this legal!?! Works for GCC... humm
char PAD1[T_Align - sizeof( int )];
};
struct SExampleImpl
{
int m_iExampleState;
};
template< typename T_Impl, size_t T_Align /* snip */ >
class TExample
{

public:

TExample() : m_pImpl( 0 ), m_pImplMem( 0 )
{
// Assert
if ( ! T_Align ||
T_Align != 1 && ( ((ptrdiff_t)m_pImpl) % sizeof( size_t ) ) )
{
throw;
}

// Alloc and align
m_pImplMem = ::operator new( sizeof( T_Impl ) + ( T_Align - 1 ) );

m_pImpl = new ( (void*)(( (((ptrdiff_t)m_pImplMem) + (T_Align - 1))
& -(T_Align) )) ) T_Impl;

// Assert
if ( T_Align != 1 && ( ((ptrdiff_t)m_pImpl) % T_Align ) )
{
m_pImpl->~T_Impl();
::operator delete( m_pImplMem );

throw;
}

std::cout << m_pImpl << "::sizeof - " << sizeof( *m_pImpl ) <<
std::endl;

// Init impl
m_pImpl->m_iExampleState = 0;
}

~TExample()
{
assert( m_pImpl && m_pImplMem );

// Dtor, placement new...
m_pImpl->~T_Impl();
::operator delete( m_pImplMem );
}
public:
// snip
private:

T_Impl *m_pImpl;
void *m_pImplMem;
};
// Now I can create a number of different padding and alignments

typedef TExample< TExampleImpl_Padded< AC_CACHE_LINE >, AC_CACHE_LINE >
CExample;
typedef TExample< TExampleImpl_Padded< AC_ALGO1_ALIGN >, AC_ALGO1_ALIGN >
CExampleAlgo1;
typedef TExample< TExampleImpl_Padded< AC_ALGO2_ALIGN >, AC_ALGO2_ALIGN >
CExampleAlgo2;
typedef TExample< SExampleImpl, 1 > CLwExample;


int main()
{
CExample s;
CExampleAlgo1 sa1;
CExampleAlgo2 sa2;
CLwExample lws;

return 0;
}
As you can see, this provides the solution I want, and passes all of the
library's tests, but...

Is this a non-portable crappy solution? If so, got anything better? I'm not
that good at C++, I'm a C guy...

;)

Thank you.


Jul 22 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.