diff --git a/include/ircd/allocator.h b/include/ircd/allocator.h index 9dca9066a..c796ad7a3 100644 --- a/include/ircd/allocator.h +++ b/include/ircd/allocator.h @@ -127,6 +127,7 @@ struct ircd::allocator::state public: bool available(const size_t &n = 1) const; void deallocate(const uint &p, const size_t &n); + uint allocate(std::nothrow_t, const size_t &n, const uint &hint = -1); uint allocate(const size_t &n, const uint &hint = -1); state(const size_t &size = 0, @@ -158,6 +159,12 @@ struct ircd::allocator::fixed std::array buf; public: + bool in_range(const T *const &ptr) const + { + const auto base(reinterpret_cast(buf.data())); + return ptr >= base && ptr < base + MAX; + } + allocator operator()(); operator allocator(); @@ -209,6 +216,14 @@ struct ircd::allocator::fixed::allocator return &x; } + pointer allocate(std::nothrow_t, const size_type &n, const const_pointer &hint = nullptr) + { + const auto base(reinterpret_cast(s->buf.data())); + const uint hintpos(hint? hint - base : -1); + const pointer ret(base + s->state::allocate(std::nothrow, n, hintpos)); + return s->in_range(ret)? ret : nullptr; + } + pointer allocate(const size_type &n, const const_pointer &hint = nullptr) { const auto base(reinterpret_cast(s->buf.data())); diff --git a/ircd/allocator.cc b/ircd/allocator.cc index 176d8f15c..a977830fb 100644 --- a/ircd/allocator.cc +++ b/ircd/allocator.cc @@ -86,10 +86,26 @@ ircd::allocator::state::deallocate(const uint &pos, uint ircd::allocator::state::allocate(const size_type &n, const uint &hint) +{ + const auto ret + { + allocate(std::nothrow, n, hint) + }; + + if(unlikely(ret >= size)) + throw std::bad_alloc(); + + return ret; +} + +uint +ircd::allocator::state::allocate(std::nothrow_t, + const size_type &n, + const uint &hint) { const auto next(this->next(n)); if(unlikely(next >= size)) // No block of n was found anywhere (next is past-the-end) - throw std::bad_alloc(); + return next; for(size_t i(0); i < n; ++i) {