UPD: Забыл сказать - доступ к элементу пула должет быть именно по индексу, а не по адресу обекта пула. Поэтому одного SLIST (когда бы Index_in_pool включал бы указатель на ptr = new Pool_entry_t() вместо индекса) без Pool_entry_t m_pool[pool_size] недостаточно. Это часть бизнес логики.
Ищется таковой. Чтобы было просто, и самое главное работало быстро (без высокого контеншн) для 5-10 thread-ов на multi-core box. Самое тривиальное, что приходит на ум - ниже. Сейчас очень модно lock-free решения. Может кто подскажет альтернативу тому, что ниже?
template <typename Pool_entry_t, size_t pool_size>
class Pool_t
{
public:
Pool_t()
{
::InitializeSListHead(&m_pool_index_head);
for(size_t i = 0; i < pool_size; i++)
{
Index_in_pool* pindex = new Index_in_pool(i);
::InterlockedPushEntrySList(&m_pool_index_head, pindex);
}
}
~Pool_t()
{
::InterlockedFlushSList(&m_pool_index_head);
}
typedef SLIST_HEADER DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) SLIST_HEADER_;
struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) Index_in_pool: SLIST_ENTRY
{
size_t m_index;
Index_in_pool(size_t index): m_index(index){}
void* operator new(size_t)
{
void*p = ::_aligned_malloc(sizeof(Index_in_pool),MEMORY_ALLOCATION_ALIGNMENT);
if (p == NULL)
{
::RaiseException( STATUS_NONCONTINUABLE_EXCEPTION, 0, 0, 0);
}
else
{
}
return p;
}
void operator delete (void *p)
{
::_aligned_free(p);
}
};
Index_in_pool* alloc_entry(void)
{
return (Index_in_pool*) ::InterlockedPopEntrySList(&m_pool_index_head);
}
void release_entry(Index_in_pool* pentry)
{
::InterlockedPushEntrySList(&m_pool_index_head, pentry);
}
Pool_entry_t* get_entry(size_t index)
{
return m_pool + index;
}
Pool_entry_t m_pool[pool_size];
SLIST_HEADER_ m_pool_index_head;
};
---
Использовать приблизительно так:
Pool_t<test_buffer, 5> g_buffer_pool;
bool simulate_pool_work(void)
{
Pool_t<test_buffer, 5>::Index_in_pool* pentry = g_buffer_pool.alloc_entry();
test_buffer* ptr_buffer = g_buffer_pool.get_entry(pentry->m_index);
for (int i = 0; i < 1; i++)
{
ptr_buffer->write();
if (!ptr_buffer->read())
{
return false;
}
else
{
}
}
g_buffer_pool.release_entry(pentry);
return true;
}
---
|