Switches indexed handles to shared_ptr (#101)

As discussed, the old method of was going to have issues, and was not
going to help in the case of the structs containing pointers. I think we
are just going to have to be careful, as guarenteeing the internal
pointers are const is going to be very difficult.
This commit is contained in:
Thad House
2016-06-18 00:59:54 -07:00
committed by Peter Johnson
parent 085c47b671
commit 3cacc2aba6
2 changed files with 34 additions and 67 deletions

View File

@@ -12,15 +12,13 @@
#include <memory>
#include <vector>
#include "HAL/Errors.h"
#include "HAL/Handles.h"
#include "HAL/cpp/priority_mutex.h"
#include "HandlesInternal.h"
namespace hal {
constexpr int32_t IndexedResourceIndexOutOfRange = -1;
constexpr int32_t IndexedResourceNotAllocated = -2;
/**
* The IndexedHandleResource class is a way to track handles. This version
* allows a limited number of handles that are allocated by index.
@@ -41,57 +39,47 @@ class IndexedHandleResource {
public:
IndexedHandleResource(const IndexedHandleResource&) = delete;
IndexedHandleResource operator=(const IndexedHandleResource&) = delete;
IndexedHandleResource();
THandle Allocate(int16_t index, const TStruct& toSet);
TStruct Get(THandle handle, int32_t* status);
IndexedHandleResource() = default;
THandle Allocate(int16_t index, int32_t* status);
std::shared_ptr<TStruct> Get(THandle handle);
void Free(THandle handle);
private:
TStruct m_structures[size];
bool m_allocated[size];
std::shared_ptr<TStruct> m_structures[size];
priority_mutex m_handleMutexes[size];
};
template <typename THandle, typename TStruct, int16_t size,
HalHandleEnum enumValue>
IndexedHandleResource<THandle, TStruct, size,
enumValue>::IndexedHandleResource() {
// ensure all allocations are initially false.
for (int i = 0; i < size; i++) {
m_allocated[i] = false;
}
}
template <typename THandle, typename TStruct, int16_t size,
HalHandleEnum enumValue>
THandle IndexedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
int16_t index, const TStruct& toSet) {
int16_t index, int32_t* status) {
// don't aquire the lock if we can fail early.
if (index < 0 || index >= size) return HAL_INVALID_HANDLE;
if (index < 0 || index >= size) {
*status = PARAMETER_OUT_OF_RANGE;
return HAL_INVALID_HANDLE;
}
std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
// check for allocation, otherwise allocate and return a valid handle
if (m_allocated[index]) return HAL_INVALID_HANDLE;
m_allocated[index] = true;
m_structures[index] = toSet;
if (m_structures[index] != nullptr) {
*status = RESOURCE_IS_ALLOCATED;
return HAL_INVALID_HANDLE;
}
m_structures[index] = std::make_shared<TStruct>();
return (THandle)hal::createHandle(index, enumValue);
}
template <typename THandle, typename TStruct, int16_t size,
HalHandleEnum enumValue>
TStruct IndexedHandleResource<THandle, TStruct, size, enumValue>::Get(
THandle handle, int32_t* status) {
std::shared_ptr<TStruct>
IndexedHandleResource<THandle, TStruct, size, enumValue>::Get(THandle handle) {
// get handle index, and fail early if index out of range or wrong handle
int16_t index = getHandleTypedIndex(handle, enumValue);
if (index < 0 || index >= size) {
*status = IndexedResourceIndexOutOfRange;
return TStruct();
return nullptr;
}
std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
// check for already deallocated handle, then return structure
if (!m_allocated[index]) {
*status = IndexedResourceNotAllocated;
return TStruct();
}
// return structure. Null will propogate correctly, so no need to manually
// check.
return m_structures[index];
}
@@ -104,6 +92,6 @@ void IndexedHandleResource<THandle, TStruct, size, enumValue>::Free(
if (index < 0 || index >= size) return;
// lock and deallocated handle
std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
m_allocated[index] = false;
m_structures[index].reset();
}
}

View File

@@ -18,9 +18,6 @@
namespace hal {
constexpr int32_t LimitedResourceIndexOutOfRange = -1;
constexpr int32_t LimitedResourceNotAllocated = -2;
/**
* The LimitedHandleResource class is a way to track handles. This version
* allows a limited number of handles that are allocated sequentially.
@@ -39,42 +36,29 @@ class LimitedHandleResource {
public:
LimitedHandleResource(const LimitedHandleResource&) = delete;
LimitedHandleResource operator=(const LimitedHandleResource&) = delete;
LimitedHandleResource();
THandle Allocate(const TStruct& toSet);
TStruct Get(THandle handle, int32_t* status);
LimitedHandleResource() = default;
THandle Allocate();
std::shared_ptr<TStruct> Get(THandle handle);
void Free(THandle handle);
private:
TStruct m_structures[size];
bool m_allocated[size];
std::shared_ptr<TStruct> m_structures[size];
priority_mutex m_handleMutexes[size];
priority_mutex m_allocateMutex;
};
template <typename THandle, typename TStruct, int16_t size,
HalHandleEnum enumValue>
LimitedHandleResource<THandle, TStruct, size,
enumValue>::LimitedHandleResource() {
// ensure all allocations are initially false.
for (int i = 0; i < size; i++) {
m_allocated[i] = false;
}
}
template <typename THandle, typename TStruct, int16_t size,
HalHandleEnum enumValue>
THandle LimitedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
const TStruct& toSet) {
THandle LimitedHandleResource<THandle, TStruct, size, enumValue>::Allocate() {
// globally lock to loop through indices
std::lock_guard<priority_mutex> sync(m_allocateMutex);
int16_t i;
for (i = 0; i < size; i++) {
if (m_allocated[i] == false) {
if (m_structures[i] == nullptr) {
// if a false index is found, grab its specific mutex
// and allocate it.
std::lock_guard<priority_mutex> sync(m_handleMutexes[i]);
m_allocated[i] = true;
m_structures[i] = toSet;
m_structures[i] = std::make_shared<TStruct>();
return (THandle)createHandle(i, enumValue);
}
}
@@ -83,21 +67,16 @@ THandle LimitedHandleResource<THandle, TStruct, size, enumValue>::Allocate(
template <typename THandle, typename TStruct, int16_t size,
HalHandleEnum enumValue>
TStruct LimitedHandleResource<THandle, TStruct, size, enumValue>::Get(
THandle handle, int32_t* status) {
*status = 0;
std::shared_ptr<TStruct>
LimitedHandleResource<THandle, TStruct, size, enumValue>::Get(THandle handle) {
// get handle index, and fail early if index out of range or wrong handle
int16_t index = getHandleTypedIndex(handle, enumValue);
if (index < 0 || index >= size) {
*status = LimitedResourceIndexOutOfRange;
return TStruct();
return nullptr;
}
std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
// check for already deallocated handle, then return structure
if (!m_allocated[index]) {
*status = LimitedResourceNotAllocated;
return TStruct();
}
// return structure. Null will propogate correctly, so no need to manually
// check.
return m_structures[index];
}
@@ -111,6 +90,6 @@ void LimitedHandleResource<THandle, TStruct, size, enumValue>::Free(
// lock and deallocated handle
std::lock_guard<priority_mutex> sync(m_allocateMutex);
std::lock_guard<priority_mutex> lock(m_handleMutexes[index]);
m_allocated[index] = false;
m_structures[index].reset();
}
}