blob: e1f102030aaf3dbe3ea0c9a9c80be88f1d127a09 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_FIDL_LLCPP_FAILOVER_ALLOCATOR_H_
#define LIB_FIDL_LLCPP_FAILOVER_ALLOCATOR_H_
#include <zircon/assert.h>
#include "allocator.h"
namespace fidl {
// FailoverHeapAllocator first tries to allocate a given object using the specified InnerAllocator.
// If no space is available, it heap allocates the object.
// InnerAllocator must implement Allocator.
// Here is an example of a allocator with a 2Kb buffer before it touches the heap:
// FailoverHeapAllocator<UnsafeBufferAllocator<2048>>()
// (aka BufferThenHeapAllocator<2048>)
template <typename InnerAllocatorType, typename... Args>
class FailoverHeapAllocator : public Allocator {
public:
FailoverHeapAllocator(Args... args) : inner_allocator_(args...) {}
static_assert(std::is_base_of<Allocator, InnerAllocatorType>::value,
"Inner allocator must implement Allocator class");
InnerAllocatorType& inner_allocator() { return inner_allocator_; }
private:
InnerAllocatorType inner_allocator_;
allocation_result allocate(AllocationType type, size_t obj_size, size_t count,
destructor dtor) override {
Allocator& allocator = inner_allocator_;
allocation_result result = allocator.allocate(type, obj_size, count, dtor);
if (result.data != nullptr) {
return result;
}
ZX_DEBUG_ASSERT(!result.data);
return allocation_result{
.data = nullptr,
// Regardless of what result from delegate allocator said, have fidl::Allocator perform heap
// allocation compatible with later delete/delete[]. The heap allocation needs to be
// performed by fidl::Allocator::make<T>() because make<>() has the type T, which is needed
// by the new/new[] expression, which is needed to be compatible with delete/delete[] in the
// general case.
.heap_allocate = true,
};
}
};
template <typename T, typename... Args>
class FailoverHeapAllocator<FailoverHeapAllocator<T>, Args...> {
private:
// This is intentionally impossible to create, since nesting FailoverHeapAllocator within
// FailoverHeapAllocator isn't what anyone actually wants (so far at least).
FailoverHeapAllocator() = delete;
FailoverHeapAllocator(const FailoverHeapAllocator& to_copy) = delete;
FailoverHeapAllocator& operator=(const FailoverHeapAllocator& to_copy) = delete;
FailoverHeapAllocator(FailoverHeapAllocator&& to_move) = delete;
FailoverHeapAllocator& operator=(FailoverHeapAllocator&& to_move) = delete;
};
} // namespace fidl
#endif // LIB_FIDL_LLCPP_FAILOVER_ALLOCATOR_H_