Commit 5eeb125b authored by Kenton Varda's avatar Kenton Varda

Work around varying OS support for aligned_alloc().

parent 75d4177c
...@@ -123,6 +123,12 @@ kj::Array<HashBucket> rehash(kj::ArrayPtr<const HashBucket> oldBuckets, size_t t ...@@ -123,6 +123,12 @@ kj::Array<HashBucket> rehash(kj::ArrayPtr<const HashBucket> oldBuckets, size_t t
// ======================================================================================= // =======================================================================================
// BTree // BTree
#if _WIN32
#define aligned_free _aligned_free
#else
#define aligned_free ::free
#endif
BTreeImpl::BTreeImpl() BTreeImpl::BTreeImpl()
: tree(const_cast<NodeUnion*>(&EMPTY_NODE)), : tree(const_cast<NodeUnion*>(&EMPTY_NODE)),
treeCapacity(1), treeCapacity(1),
...@@ -133,7 +139,7 @@ BTreeImpl::BTreeImpl() ...@@ -133,7 +139,7 @@ BTreeImpl::BTreeImpl()
endLeaf(0) {} endLeaf(0) {}
BTreeImpl::~BTreeImpl() noexcept(false) { BTreeImpl::~BTreeImpl() noexcept(false) {
if (tree != &EMPTY_NODE) { if (tree != &EMPTY_NODE) {
::free(tree); aligned_free(tree);
} }
} }
...@@ -221,12 +227,36 @@ void BTreeImpl::clear() { ...@@ -221,12 +227,36 @@ void BTreeImpl::clear() {
void BTreeImpl::growTree(uint minCapacity) { void BTreeImpl::growTree(uint minCapacity) {
uint newCapacity = kj::max(kj::max(minCapacity, treeCapacity * 2), 4); uint newCapacity = kj::max(kj::max(minCapacity, treeCapacity * 2), 4);
freelistSize += newCapacity - treeCapacity; freelistSize += newCapacity - treeCapacity;
// Allocate some aligned memory! In theory this should be as simple as calling the C11 standard
// aligned_alloc() function. Unfortunately, many platforms don't implement it. Luckily, there
// are usually alternatives.
#if __APPLE__
// OSX lacks aligned_alloc(), but has posix_memalign(). Fine.
void* allocPtr;
int error = posix_memalign(&allocPtr,
sizeof(BTreeImpl::NodeUnion), newCapacity * sizeof(BTreeImpl::NodeUnion));
if (error != 0) {
KJ_FAIL_SYSCALL("posix_memalign", error);
}
NodeUnion* newTree = reinterpret_cast<NodeUnion*>(allocPtr);
#elif _WIN32
// Windows lacks aligned_alloc() but has its own _aligned_malloc() (which requires freeing using
// _aligned_free()).
NodeUnion* newTree = reinterpret_cast<NodeUnion*>(
_aligned_malloc(sizeof(BTreeImpl::NodeUnion), newCapacity * sizeof(BTreeImpl::NodeUnion)));
KJ_ASSERT(newTree != nullptr, "memory allocation failed", newCapacity);
#else
// Let's use the C11 standard.
NodeUnion* newTree = reinterpret_cast<NodeUnion*>( NodeUnion* newTree = reinterpret_cast<NodeUnion*>(
aligned_alloc(sizeof(BTreeImpl::NodeUnion), newCapacity * sizeof(BTreeImpl::NodeUnion))); aligned_alloc(sizeof(BTreeImpl::NodeUnion), newCapacity * sizeof(BTreeImpl::NodeUnion)));
KJ_ASSERT(newTree != nullptr, "memory allocation failed", newCapacity); KJ_ASSERT(newTree != nullptr, "memory allocation failed", newCapacity);
#endif
acopy(newTree, tree, treeCapacity); acopy(newTree, tree, treeCapacity);
azero(newTree + treeCapacity, newCapacity - treeCapacity); azero(newTree + treeCapacity, newCapacity - treeCapacity);
if (tree != &EMPTY_NODE) ::free(tree); if (tree != &EMPTY_NODE) aligned_free(tree);
tree = newTree; tree = newTree;
treeCapacity = newCapacity; treeCapacity = newCapacity;
} }
......
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