(чтобы предоставить информацию, необходимую для понимания моего вопроса, достаточно много, но он уже сжат)
Я пытаюсь реализовать шаблон класса для распределения и доступа к кэшу данных.Это работает очень хорошо, однако попытка реализовать поддержку массивов является проблемой.
Семантически код должен обеспечивать это отображение в памяти для одного элемента, подобного этому:
cache_aligned<element_type>* my_el =
new(cache_line_size) cache_aligned<element_type>();
| element | buffer |
access (пока) выглядит так:
*my_el; // returns cache_aligned<element_type>
**my_el; //returns element_type
*my_el->member_of_element();
ОДНАКО для массива, я хотел бы иметь это:
cache_aligned<element_type>* my_el_array =
new(cache_line_size) cache_aligned<element_type()[N];
| element 0 | buffer | element 1 | buffer | ... | element (N-1) | buffer |
Пока у меня есть следующий код
template <typename T>
class cache_aligned {
private:
T instance;
public:
cache_aligned()
{}
cache_aligned(const T& other)
:instance(other.instance)
{}
static void* operator new (size_t size, uint c_line_size) {
return c_a_malloc(size, c_line_size);
}
static void* operator new[] (size_t size, uint c_line_size) {
int num_el = (size - sizeof(cache_aligned<T>*)
/ sizeof(cache_aligned<T>);
return c_a_array(sizeof(cache_aligned<T>), num_el, c_line_size);
}
static void operator delete (void* ptr) {
free_c_a(ptr);
}
T* operator-> () {
return &instance;
}
T& operator * () {
return instance;
}
};
функции cache_aligned_malloc
void* c_a_array(uint size, ulong num_el, uint c_line_size) {
void* mem = malloc((size + c_line_size) * num_el + sizeof(void*));
void** ptr = (void**)((long)mem + sizeof(void*));
ptr[-1] = mem;
return ptr;
}
void free_c_a(void ptr) {
free(((void**)ptr)[-1]);
}
Проблема здесь, доступ к данным должен работать следующим образом:
my_el_array[i]; // returns cache_aligned<element_type>
*(my_el_array[i]); // returns element_type
my_el_array[i]->member_of_element();
Мои идеи для ее решения:
(1) что-то похожее на это, чтобы перегрузить оператор sizeof:
static size_t operator sizeof () {
return sizeof(cache_aligned<T>) + c_line_size;
}
-> невозможно, так как перегрузка оператора sizeof недопустима
(2) что-то вроде этого,перегрузить оператор [] для типа указателя:
static T& operator [] (uint index, cache_aligned<T>* ptr) {
return ptr + ((sizeof(cache_aligned<T>) + c_line_size) * index);
}
-> невозможно в C ++, в любом случае
(3) полностью тривиальное решение
template <typename T> cache_aligned {
private:
T instance;
bool buffer[CACHE_LINE_SIZE];
// CACHE_LINE_SIZE defined as macro
public:
// trivial operators and methods ;)
};
-> Я не знаю, насколько это надежно, на самом деле я использую gcc-4.5.1 в Linux ...
(4) Replдействующий экземпляр T;по T * instance_ptr;в шаблоне класса и используя оператор [] для вычисления положения элемента, например:
|указатель на экземпляр |----> |элемент 0 |буфер |... |элемент (N-1) |buffer |
это не предполагаемая семантика, так как экземпляр шаблона класса становится узким местом при вычислении адреса элементов.
Спасибо за чтение!Я не знаю, как сократить проблему.Было бы здорово, если бы вы могли помочь!Любой обходной путь очень помог бы.
Я знаю, что выравнивание - это расширение в C ++ 0x.Однако в gcc он еще не доступен.
Greetz, sema