C
Chris Thomasson
I found some time to work a little more on my C++ allocator project. Here is
some of the basic alignment code that I am thinking about using:
----------------
#include <cstdio>
#include <cstring>
#include <cassert>
// attempts to extract the alignemnt of a type T
template<typename T>
class align_of {
struct temp {
char m_offset;
T m_object;
};
public:
enum result_e {
c_result = sizeof(temp) > sizeof(T) ?
sizeof(temp) - sizeof(T) : sizeof(T)
};
};
// attempts to extract an aligned buffer from _this
template<typename T>
static char* align_ptr(
char const* const _this,
ptrdiff_t alignsz = align_of<T>::c_result
) {
ptrdiff_t offsetsz =
reinterpret_cast<ptrdiff_t>(_this) % alignsz;
if (offsetsz) {
assert(offsetsz < alignsz);
char const* const offsetptr =
reinterpret_cast<char const*>(_this) + alignsz - offsetsz;
if (reinterpret_cast<ptrdiff_t>(offsetptr) % alignsz) {
assert(! (reinterpret_cast<ptrdiff_t>(offsetptr) % alignsz));
throw;
}
printf("%p alignptr(%p, %i); // offset %i\n",
(void*)offsetptr, (void*)_this, alignsz, offsetsz);
return const_cast<char*>(offsetptr);
}
printf("%p alignptr(%p, %i);\n",
(void*)_this, (void*)_this, alignsz);
return const_cast<char*>(_this);
}
// a buffer and an aligned pointer into it...
template<size_t T_sz, ptrdiff_t T_alignsz = T_sz>
struct aligned_buf {
enum const_e {
c_alignsz = T_alignsz,
c_alignobjsz = T_sz + c_alignsz - 1
};
char c_bufraw[c_alignobjsz];
char* const c_bufalign;
aligned_buf() :
c_bufalign(align_ptr<char>(c_bufraw, c_alignsz)) {
memset(c_bufraw, 0, c_alignobjsz);
}
char* load_align_ptr(ptrdiff_t alignsz) const {
char* const ptr = align_ptr<char>(c_bufalign, alignsz);
return ptr;
}
};
/* App
____________________________________________________*/
// platform specific
namespace platform {
namespace os {
enum const_e {
c_pagesz = 8192
};
}
namespace arch {
enum const_e {
c_l2cachelinesz = 128
};
}
}
// misc types...
struct temp1 {
char m_1;
short m_2;
};
struct temp2 {
char m_1;
temp1 m_2;
float m_3;
};
struct temp3 {
char m_1;
temp2 m_2;
double m_3;
};
// os page(s) w/ page-boundary alignment type
template<size_t T_pages>
struct pagebuf {
typedef aligned_buf<
platform:s::c_pagesz * T_pages,
platform:s::c_pagesz> pagebuf_t;
// pagebuf is os page aligned on page-boundary
pagebuf_t m_buf;
};
int main(void) {
{
// create 4 pages on the stack.
typedef pagebuf<4> pages_t;
pages_t pages;
// l2cachebuf is aligned off of pagebuf
char* const l2cachebuf =
pages.m_buf.load_align_ptr(platform::arch::c_l2cachelinesz);
// display page alignment info
printf("\n\n\
(%u)-pages sizeof\n\
(%p)-pages.m_buf.c_bufraw\n\
(%p)-pages.m_buf.c_bufalign\n\
(%p)-l2cachebuf\n",
sizeof(pages),
(void*)pages.m_buf.c_bufraw,
(void*)pages.m_buf.c_bufalign,
(void*)l2cachebuf);
// display basic type alignment info
printf("\n\n\
(sz:%u\talign:%i)-char\n\
(sz:%u\talign:%i)-short\n\
(sz:%u\talign:%i)-long\n\
(sz:%u\talign:%i)-float\n\
(sz:%u\talign:%i)-double\n\
(sz:%u\talign:%i)-long double\n\
(sz:%u\talign:%i)-void* align\n\
(sz:%u\talign:%i)-void* (*) (void*)\n\
(sz:%u\talign:%i)-temp1\n\
(sz:%u\talign:%i)-temp2\n\
(sz:%u\talign:%i)-temp3\n",
sizeof(char), align_of<char>::c_result,
sizeof(short), align_of<short>::c_result,
sizeof(long), align_of<long>::c_result,
sizeof(float), align_of<float>::c_result,
sizeof(double), align_of<double>::c_result,
sizeof(long double), align_of<long double>::c_result,
sizeof(void*), align_of<void*>::c_result,
sizeof(void* (*) (void*)), align_of<void* (*) (void*)>::c_result,
sizeof(temp1), align_of<temp1>::c_result,
sizeof(temp2), align_of<temp2>::c_result,
sizeof(temp3), align_of<temp3>::c_result);
}
puts("\n\n\n\
_______________________\npress <enter> to exit...\n");
return getchar();
}
----------------
This alignment code will be used in a per-thread C++ allocator scheme. I am
always looking for better ways of doing the "alignment" stuff. If you have
any suggestions I would like to hear them...
some of the basic alignment code that I am thinking about using:
----------------
#include <cstdio>
#include <cstring>
#include <cassert>
// attempts to extract the alignemnt of a type T
template<typename T>
class align_of {
struct temp {
char m_offset;
T m_object;
};
public:
enum result_e {
c_result = sizeof(temp) > sizeof(T) ?
sizeof(temp) - sizeof(T) : sizeof(T)
};
};
// attempts to extract an aligned buffer from _this
template<typename T>
static char* align_ptr(
char const* const _this,
ptrdiff_t alignsz = align_of<T>::c_result
) {
ptrdiff_t offsetsz =
reinterpret_cast<ptrdiff_t>(_this) % alignsz;
if (offsetsz) {
assert(offsetsz < alignsz);
char const* const offsetptr =
reinterpret_cast<char const*>(_this) + alignsz - offsetsz;
if (reinterpret_cast<ptrdiff_t>(offsetptr) % alignsz) {
assert(! (reinterpret_cast<ptrdiff_t>(offsetptr) % alignsz));
throw;
}
printf("%p alignptr(%p, %i); // offset %i\n",
(void*)offsetptr, (void*)_this, alignsz, offsetsz);
return const_cast<char*>(offsetptr);
}
printf("%p alignptr(%p, %i);\n",
(void*)_this, (void*)_this, alignsz);
return const_cast<char*>(_this);
}
// a buffer and an aligned pointer into it...
template<size_t T_sz, ptrdiff_t T_alignsz = T_sz>
struct aligned_buf {
enum const_e {
c_alignsz = T_alignsz,
c_alignobjsz = T_sz + c_alignsz - 1
};
char c_bufraw[c_alignobjsz];
char* const c_bufalign;
aligned_buf() :
c_bufalign(align_ptr<char>(c_bufraw, c_alignsz)) {
memset(c_bufraw, 0, c_alignobjsz);
}
char* load_align_ptr(ptrdiff_t alignsz) const {
char* const ptr = align_ptr<char>(c_bufalign, alignsz);
return ptr;
}
};
/* App
____________________________________________________*/
// platform specific
namespace platform {
namespace os {
enum const_e {
c_pagesz = 8192
};
}
namespace arch {
enum const_e {
c_l2cachelinesz = 128
};
}
}
// misc types...
struct temp1 {
char m_1;
short m_2;
};
struct temp2 {
char m_1;
temp1 m_2;
float m_3;
};
struct temp3 {
char m_1;
temp2 m_2;
double m_3;
};
// os page(s) w/ page-boundary alignment type
template<size_t T_pages>
struct pagebuf {
typedef aligned_buf<
platform:s::c_pagesz * T_pages,
platform:s::c_pagesz> pagebuf_t;
// pagebuf is os page aligned on page-boundary
pagebuf_t m_buf;
};
int main(void) {
{
// create 4 pages on the stack.
typedef pagebuf<4> pages_t;
pages_t pages;
// l2cachebuf is aligned off of pagebuf
char* const l2cachebuf =
pages.m_buf.load_align_ptr(platform::arch::c_l2cachelinesz);
// display page alignment info
printf("\n\n\
(%u)-pages sizeof\n\
(%p)-pages.m_buf.c_bufraw\n\
(%p)-pages.m_buf.c_bufalign\n\
(%p)-l2cachebuf\n",
sizeof(pages),
(void*)pages.m_buf.c_bufraw,
(void*)pages.m_buf.c_bufalign,
(void*)l2cachebuf);
// display basic type alignment info
printf("\n\n\
(sz:%u\talign:%i)-char\n\
(sz:%u\talign:%i)-short\n\
(sz:%u\talign:%i)-long\n\
(sz:%u\talign:%i)-float\n\
(sz:%u\talign:%i)-double\n\
(sz:%u\talign:%i)-long double\n\
(sz:%u\talign:%i)-void* align\n\
(sz:%u\talign:%i)-void* (*) (void*)\n\
(sz:%u\talign:%i)-temp1\n\
(sz:%u\talign:%i)-temp2\n\
(sz:%u\talign:%i)-temp3\n",
sizeof(char), align_of<char>::c_result,
sizeof(short), align_of<short>::c_result,
sizeof(long), align_of<long>::c_result,
sizeof(float), align_of<float>::c_result,
sizeof(double), align_of<double>::c_result,
sizeof(long double), align_of<long double>::c_result,
sizeof(void*), align_of<void*>::c_result,
sizeof(void* (*) (void*)), align_of<void* (*) (void*)>::c_result,
sizeof(temp1), align_of<temp1>::c_result,
sizeof(temp2), align_of<temp2>::c_result,
sizeof(temp3), align_of<temp3>::c_result);
}
puts("\n\n\n\
_______________________\npress <enter> to exit...\n");
return getchar();
}
----------------
This alignment code will be used in a per-thread C++ allocator scheme. I am
always looking for better ways of doing the "alignment" stuff. If you have
any suggestions I would like to hear them...