blob: 2fbe030c206e87bc444c5c6c846a910359dd7ec8 [file] [log] [blame]
/*
* Copyright (C) 2022 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 CHRE_UTIL_SYNCHRONIZED_EXPANDABLE_MEMORY_POOL_H_
#define CHRE_UTIL_SYNCHRONIZED_EXPANDABLE_MEMORY_POOL_H_
#include "chre/platform/mutex.h"
#include "chre/util/fixed_size_vector.h"
#include "chre/util/memory_pool.h"
#include "chre/util/unique_ptr.h"
namespace chre {
/**
* This is a similar data structure to chre::SynchronizedMemoryPool with a more
* optimized memory usage. This data structure will allocate new storage as
* needed and in segments as appose to SynchronizedMemoryPool that allocates the
* entire storage once and as a continuous block. It will also deallocates
* storage once it's not used for a long time to balance memory usage and
* thrashing. These properties lead to a lower memory usage in average time and
* also prevents heap fragmentation.
*
* @tparam ElementType the element to store in ths expandable memory pool.
* @tparam kMemoryPoolSize the size of each element pool (each block).
* @tparam kMaxMemoryPoolCount the maximum number of memory blocks.
*/
template <typename ElementType, size_t kMemoryPoolSize,
size_t kMaxMemoryPoolCount>
class SynchronizedExpandableMemoryPool : public NonCopyable {
using Block = ::chre::MemoryPool<ElementType, kMemoryPoolSize>;
static_assert(kMemoryPoolSize > 0);
public:
/**
* Construct a new Synchronized Expandable Memory Pool object.
* The maximum memory that this pool will allocate is maxMemoryPoolCount
* kMemoryPoolSize * sizeof(ElementType).
*
* @param staticBlockCount the number of blocks that will be allocate in the
* constructor and will only be deallocate by the destructor. Needs to be
* bigger than zero to avoid thrashing.
*/
SynchronizedExpandableMemoryPool(size_t staticBlockCount = 1);
/**
* Allocates space for an object, constructs it and returns the pointer to
* that object. This method is thread-safe and a lock will be acquired
* upon entry to this method.
*
* @param The arguments to be forwarded to the constructor of the object.
* @return A pointer to a constructed object or nullptr if the allocation
* fails.
*/
template <typename... Args>
ElementType *allocate(Args &&...args);
/**
* Releases the memory of a previously allocated element. The pointer provided
* here must be one that was produced by a previous call to the allocate()
* function. The destructor is invoked on the object. This method is
* thread-safe and a lock will be acquired upon entry to this method.
*
* @param A pointer to an element that was previously allocated by the
* allocate() function.
*/
void deallocate(ElementType *element);
/**
* @return the number of new element that this memory pool can add.
*/
size_t getFreeSpaceCount();
/**
* @return size_t Return the number of blocks currently in the memory pool.
*/
size_t getBlockCount();
/**
* @return if the memory pool is full.
*/
inline bool full();
private:
//! Number of blocks that will be allocate in the beginning and will only be
//! deallocate by the destructor.
const size_t kStaticBlockCount;
//! Number of elements that this memory pool currently hold.
size_t mSize = 0;
//! The mutex used to guard access to this memory pool.
Mutex mMutex;
//! A fixed sized container that wraps around non-synchronized
//! MemoryPools used to implement this thread-safe and expandable version
//! version.
FixedSizeVector<UniquePtr<Block>, kMaxMemoryPoolCount> mMemoryPoolPtrs;
/**
* Push one memory pool to the end of the vector.
*
* @return true if a new memory pool can be allocated.
*/
bool pushOneBlock();
/**
* @return true if this block is more than half full.
*/
bool isHalfFullBlock(Block *block);
};
} // namespace chre
#include "chre/util/synchronized_expandable_memory_pool_impl.h"
#endif // CHRE_UTIL_SYNCHRONIZED_EXPANDABLE_MEMORY_POOL_H_