src: memchunks: Don't use std::unique_ptr to avoid potential SO

This commit is contained in:
Tatsuhiro Tsujikawa 2017-05-22 23:17:04 +09:00
parent 7f31278c4c
commit c57bf21306
2 changed files with 19 additions and 16 deletions

View File

@ -50,23 +50,21 @@ namespace nghttp2 {
#endif // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT
template <size_t N> struct Memchunk {
Memchunk(std::unique_ptr<Memchunk> next_chunk)
: pos(std::begin(buf)),
last(pos),
knext(std::move(next_chunk)),
next(nullptr) {}
Memchunk(Memchunk *next_chunk)
: pos(std::begin(buf)), last(pos), knext(next_chunk), next(nullptr) {}
size_t len() const { return last - pos; }
size_t left() const { return std::end(buf) - last; }
void reset() { pos = last = std::begin(buf); }
std::array<uint8_t, N> buf;
uint8_t *pos, *last;
std::unique_ptr<Memchunk> knext;
Memchunk *knext;
Memchunk *next;
static const size_t size = N;
};
template <typename T> struct Pool {
Pool() : pool(nullptr), freelist(nullptr), poolsize(0) {}
~Pool() { clear(); }
T *get() {
if (freelist) {
auto m = freelist;
@ -76,9 +74,9 @@ template <typename T> struct Pool {
return m;
}
pool = make_unique<T>(std::move(pool));
pool = new T{pool};
poolsize += T::size;
return pool.get();
return pool;
}
void recycle(T *m) {
m->next = freelist;
@ -86,11 +84,16 @@ template <typename T> struct Pool {
}
void clear() {
freelist = nullptr;
for (auto p = pool; p;) {
auto knext = p->knext;
delete p;
p = knext;
}
pool = nullptr;
poolsize = 0;
}
using value_type = T;
std::unique_ptr<T> pool;
T *pool;
T *freelist;
size_t poolsize;
};

View File

@ -42,34 +42,34 @@ void test_pool_recycle(void) {
auto m1 = pool.get();
CU_ASSERT(m1 == pool.pool.get());
CU_ASSERT(m1 == pool.pool);
CU_ASSERT(MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);
auto m2 = pool.get();
CU_ASSERT(m2 == pool.pool.get());
CU_ASSERT(m2 == pool.pool);
CU_ASSERT(2 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);
CU_ASSERT(m1 == m2->knext.get());
CU_ASSERT(nullptr == m1->knext.get());
CU_ASSERT(m1 == m2->knext);
CU_ASSERT(nullptr == m1->knext);
auto m3 = pool.get();
CU_ASSERT(m3 == pool.pool.get());
CU_ASSERT(m3 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);
pool.recycle(m3);
CU_ASSERT(m3 == pool.pool.get());
CU_ASSERT(m3 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(m3 == pool.freelist);
auto m4 = pool.get();
CU_ASSERT(m3 == m4);
CU_ASSERT(m4 == pool.pool.get());
CU_ASSERT(m4 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);