Commit 385b4994 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Defer all initialization until allocation in IndexedMemPool

Summary: [Folly] Defer all initialization until allocation in `IndexedMemPool`. This provides a better guarantee that the constructor never dirties the allocated region by accidentally direct-initializing rather than default-initializing the linked list pointers in the mapped region.

Reviewed By: davidtgoldblatt

Differential Revision: D13046558

fbshipit-source-id: 1bde547525e2502607d01e68206d7f8c826baebd
parent 3222b57b
...@@ -210,19 +210,6 @@ struct IndexedMemPool : boost::noncopyable { ...@@ -210,19 +210,6 @@ struct IndexedMemPool : boost::noncopyable {
assert(errno == ENOMEM); assert(errno == ENOMEM);
throw std::bad_alloc(); throw std::bad_alloc();
} }
// Atom is expected to be std::atomic, which is trivially
// constructible, so we can avoid explicitly initializing the
// slots which would cause the whole mapped area to be paged in.
//
// TODO: Switch to is_trivially_constructible once support
// for GCC 4.9 is dropped for this file.
if /* constexpr */ (!std::is_trivial<Atom<uint32_t>>::value) {
for (size_t i = 1; i < actualCapacity_ + 1; i++) {
// Atom is enforced above to be nothrow-default-constructible
new (&slots_[i].localNext) Atom<uint32_t>;
new (&slots_[i].globalNext) Atom<uint32_t>;
}
}
} }
/// Destroys all of the contained elements /// Destroys all of the contained elements
...@@ -230,8 +217,6 @@ struct IndexedMemPool : boost::noncopyable { ...@@ -230,8 +217,6 @@ struct IndexedMemPool : boost::noncopyable {
using A = Atom<uint32_t>; using A = Atom<uint32_t>;
for (uint32_t i = maxAllocatedIndex(); i > 0; --i) { for (uint32_t i = maxAllocatedIndex(); i > 0; --i) {
Traits::cleanup(&slots_[i].elem); Traits::cleanup(&slots_[i].elem);
}
for (size_t i = 1; i < actualCapacity_ + 1; i++) {
slots_[i].localNext.~A(); slots_[i].localNext.~A();
slots_[i].globalNext.~A(); slots_[i].globalNext.~A();
} }
...@@ -506,7 +491,14 @@ struct IndexedMemPool : boost::noncopyable { ...@@ -506,7 +491,14 @@ struct IndexedMemPool : boost::noncopyable {
// allocation failed // allocation failed
return 0; return 0;
} }
Traits::initialize(&slot(idx).elem); Slot& s = slot(idx);
// Atom is enforced above to be nothrow-default-constructible
// As an optimization, use default-initialization (no parens) rather
// than direct-initialization (with parens): these locations are
// stored-to before they are loaded-from
new (&s.localNext) Atom<uint32_t>;
new (&s.globalNext) Atom<uint32_t>;
Traits::initialize(&s.elem);
return idx; return idx;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment