/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _GTS_NANOAPPS_SHARED_DUMB_ALLOCATOR_H_
#define _GTS_NANOAPPS_SHARED_DUMB_ALLOCATOR_H_
#include <cstddef>
#include <cstdint>
namespace nanoapp_testing {
// Implementation Note: We chose the pattern of having DumbAllocatorBase to
// reduce the code duplication from multiple instances of DumbAllocator with
// different template parameters.
// See DumbAllocator below for usage and API documentation.
class DumbAllocatorBase {
protected:
DumbAllocatorBase(size_t allocSize, size_t slotCount, uint8_t *rawMemory);
void *alloc(size_t bytes);
bool free(void *ptr);
bool contains(const void *ptr) const;
static constexpr size_t MaxSlotCount() {
// Our mAllocatedSlots is treated as a bit array, so we get 8 slots for
// each byte it has.
return (sizeof(mAllocatedSlots) * 8);
}
private:
const size_t mAllocSize;
const size_t mSlotCount;
uint8_t * const mRawMemory;
uint32_t mAllocatedSlots;
bool getSlot(const void *ptr, size_t *slot) const;
};
/**
* This dumb allocator is designed to allow us to easily get chunks of
* memory without needing to go through heap allocation. The idea is to
* reduce our dependency on CHRE for some aspects of our tests.
*
* This allocator is non-reentrant. It's also inefficient and a bad idea
* for shipping code, but useful for reducing dependencies during testing.
*
* This will allow up to kSlotCount allocations of up to kAllocSize bytes
* each, and costs (kSlotCount * kAllocSize) bytes of underlying storage.
*/
template<size_t kAllocSize, size_t kSlotCount>
class DumbAllocator : DumbAllocatorBase {
public:
DumbAllocator()
: DumbAllocatorBase(kAllocSize, kSlotCount, mRawMemoryArray) {}
/**
* If "bytes" <= kAllocSize, and there are less than kSlotCount allocations,
* return a valid pointer. Otherwise, nullptr.
*
* Reminder this is non-reentrant.
*/
void *alloc(size_t bytes) {
return DumbAllocatorBase::alloc(bytes);
}
/**
* If contains(ptr) is true, free the allocation and return true.
* Otherwise, do nothing and return false.
*
* Reminder this is non-reentrant.
*/
bool free(void *ptr) {
return DumbAllocatorBase::free(ptr);
}
/**
* If "ptr" was a non-null pointer returned from alloc() on this instance,
* return true. Otherwise, do nothing and return false.
*/
bool contains(const void *ptr) const {
return DumbAllocatorBase::contains(ptr);
}
private:
uint8_t mRawMemoryArray[kAllocSize * kSlotCount];
static_assert(kSlotCount <= MaxSlotCount(), "kSlotCount is too high");
};
} // namespace nanoapp_testing
#endif // _GTS_NANOAPPS_SHARED_DUMB_ALLOCATOR_H_