mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
add variable_alloc
This commit is contained in:
parent
15e71bd1a1
commit
56103e08dd
@ -44,12 +44,12 @@ protected:
|
|||||||
block_t* list_ = nullptr;
|
block_t* list_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void free(void* /*p*/) {}
|
|
||||||
void free(void* /*p*/, std::size_t) {}
|
|
||||||
|
|
||||||
void swap(scope_alloc_base & rhs) {
|
void swap(scope_alloc_base & rhs) {
|
||||||
std::swap(this->list_, rhs.list_);
|
std::swap(this->list_, rhs.list_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free(void* /*p*/) {}
|
||||||
|
void free(void* /*p*/, std::size_t) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -71,7 +71,6 @@ public:
|
|||||||
|
|
||||||
~scope_alloc() { clear(); }
|
~scope_alloc() { clear(); }
|
||||||
|
|
||||||
public:
|
|
||||||
void swap(scope_alloc& rhs) {
|
void swap(scope_alloc& rhs) {
|
||||||
std::swap(this->alloc_, rhs.alloc_);
|
std::swap(this->alloc_, rhs.alloc_);
|
||||||
base_t::swap(rhs);
|
base_t::swap(rhs);
|
||||||
@ -103,8 +102,7 @@ namespace detail {
|
|||||||
template <std::size_t BlockSize>
|
template <std::size_t BlockSize>
|
||||||
struct fixed_expand_policy {
|
struct fixed_expand_policy {
|
||||||
static std::size_t next(std::size_t & e) {
|
static std::size_t next(std::size_t & e) {
|
||||||
static constexpr std::size_t basic_size = (ipc::detail::max)(BlockSize, static_cast<std::size_t>(2048));
|
return (ipc::detail::max)(BlockSize, static_cast<std::size_t>(2048)) * (e *= 2);
|
||||||
return basic_size * (e *= 2);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -145,7 +143,9 @@ public:
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <std::size_t BlockSize, template <std::size_t> class ExpandP = detail::fixed_expand_policy, typename AllocP = scope_alloc<>>
|
template <std::size_t BlockSize,
|
||||||
|
template <std::size_t> class ExpandP = detail::fixed_expand_policy,
|
||||||
|
typename AllocP = scope_alloc<>>
|
||||||
class fixed_alloc : public detail::fixed_alloc_base {
|
class fixed_alloc : public detail::fixed_alloc_base {
|
||||||
public:
|
public:
|
||||||
using base_t = detail::fixed_alloc_base;
|
using base_t = detail::fixed_alloc_base;
|
||||||
@ -178,7 +178,6 @@ public:
|
|||||||
fixed_alloc(fixed_alloc&& rhs) { this->swap(rhs); }
|
fixed_alloc(fixed_alloc&& rhs) { this->swap(rhs); }
|
||||||
fixed_alloc& operator=(fixed_alloc&& rhs) { this->swap(rhs); return (*this); }
|
fixed_alloc& operator=(fixed_alloc&& rhs) { this->swap(rhs); return (*this); }
|
||||||
|
|
||||||
public:
|
|
||||||
void swap(fixed_alloc& rhs) {
|
void swap(fixed_alloc& rhs) {
|
||||||
std::swap(this->alloc_, rhs.alloc_);
|
std::swap(this->alloc_, rhs.alloc_);
|
||||||
base_t::swap(rhs);
|
base_t::swap(rhs);
|
||||||
@ -200,5 +199,126 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
/// Variable-size blocks allocation
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class variable_alloc_base {
|
||||||
|
protected:
|
||||||
|
struct head_t {
|
||||||
|
head_t * next_;
|
||||||
|
size_t size_;
|
||||||
|
size_t free_;
|
||||||
|
};
|
||||||
|
|
||||||
|
char * head_, * tail_;
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
// makes chain to nullptr
|
||||||
|
head_ = tail_ = reinterpret_cast<char*>(sizeof(head_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
head_t* chain() {
|
||||||
|
return reinterpret_cast<head_t*>(head_ - sizeof(head_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void swap(variable_alloc_base& rhs) {
|
||||||
|
std::swap(this->head_, rhs.head_);
|
||||||
|
std::swap(this->tail_, rhs.tail_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void* /*p*/) {}
|
||||||
|
void free(void* /*p*/, std::size_t) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <std::size_t ChunkSize = 4096, typename AllocP = scope_alloc<>>
|
||||||
|
class variable_alloc : public detail::variable_alloc_base {
|
||||||
|
public:
|
||||||
|
using base_t = detail::variable_alloc_base;
|
||||||
|
using head_t = base_t::head_t;
|
||||||
|
using alloc_policy = AllocP;
|
||||||
|
|
||||||
|
private:
|
||||||
|
alloc_policy alloc_;
|
||||||
|
|
||||||
|
head_t* alloc_head(std::size_t size) {
|
||||||
|
size = (ipc::detail::max)(ChunkSize, (ipc::detail::max)(size, sizeof(head_t)));
|
||||||
|
head_t* p = static_cast<head_t*>(alloc_.alloc(size));
|
||||||
|
p->free_ = (p->size_ = size) - sizeof(head_t);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_head(head_t* curr) {
|
||||||
|
alloc_.free(curr, curr->size_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t remain() const {
|
||||||
|
return (tail_ - head_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* alloc_new_chunk(std::size_t size) {
|
||||||
|
head_t* p = alloc_head(sizeof(head_t) + size);
|
||||||
|
if (p == nullptr) return nullptr;
|
||||||
|
head_t* list = chain();
|
||||||
|
if (size > (ChunkSize - sizeof(head_t)) && list != nullptr) {
|
||||||
|
p->next_ = list->next_;
|
||||||
|
list->next_ = p;
|
||||||
|
char* head = reinterpret_cast<char*>(p + 1);
|
||||||
|
char* tail = head + p->free_ - size;
|
||||||
|
p->free_ = tail - head;
|
||||||
|
return tail;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p->next_ = list;
|
||||||
|
head_ = reinterpret_cast<char*>(p + 1);
|
||||||
|
tail_ = head_ + p->free_ - size;
|
||||||
|
p->free_ = remain();
|
||||||
|
return tail_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
variable_alloc() { this->init(); }
|
||||||
|
|
||||||
|
variable_alloc(variable_alloc&& rhs) { this->swap(rhs); }
|
||||||
|
variable_alloc& operator=(variable_alloc&& rhs) { this->swap(rhs); return (*this); }
|
||||||
|
|
||||||
|
~variable_alloc() { clear(); }
|
||||||
|
|
||||||
|
void swap(variable_alloc& rhs) {
|
||||||
|
std::swap(this->alloc_, rhs.alloc_);
|
||||||
|
base_t::swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
head_t* list = chain();
|
||||||
|
while (list != nullptr) {
|
||||||
|
head_t* curr = list;
|
||||||
|
list = list->next_;
|
||||||
|
free_head(curr);
|
||||||
|
}
|
||||||
|
alloc_.clear();
|
||||||
|
this->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* alloc(size_t size) {
|
||||||
|
if (remain() < size) {
|
||||||
|
return alloc_new_chunk(size);
|
||||||
|
}
|
||||||
|
char* buff = tail_ - size;
|
||||||
|
if (buff < head_) {
|
||||||
|
return alloc_new_chunk(size);
|
||||||
|
}
|
||||||
|
tail_ = buff;
|
||||||
|
chain()->free_ = remain();
|
||||||
|
return tail_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mem
|
} // namespace mem
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
|||||||
@ -230,7 +230,9 @@ struct default_mapping_policy {
|
|||||||
static const std::size_t table[classes_size];
|
static const std::size_t table[classes_size];
|
||||||
|
|
||||||
constexpr static std::size_t classify(std::size_t size) {
|
constexpr static std::size_t classify(std::size_t size) {
|
||||||
return (((size - 1) / base_size) < classes_size) ? table[((size - 1) / base_size)] : classes_size;
|
return (((size - 1) / base_size) < classes_size) ?
|
||||||
|
// always uses default_mapping_policy<sizeof(void*)>::table
|
||||||
|
default_mapping_policy<>::table[((size - 1) / base_size)] : classes_size;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user