/*----------------------------------------------------------------------------*/ /* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ /*----------------------------------------------------------------------------*/ #pragma once #include #include #include #include #include #include "hal/Types.h" #include "hal/handles/HandlesInternal.h" namespace hal { /** * The UnlimitedHandleResource class is a way to track handles. This version * allows an unlimted number of handles that are allocated sequentially. When * possible, indices are reused to save memory usage and keep the array length * down. * However, automatic array management has not been implemented, but might be in * the future. * Because we have to loop through the allocator, we must use a global mutex. * @tparam THandle The Handle Type (Must be typedefed from HAL_Handle) * @tparam TStruct The struct type held by this resource * @tparam enumValue The type value stored in the handle * */ template class UnlimitedHandleResource : public HandleBase { friend class UnlimitedHandleResourceTest; public: UnlimitedHandleResource() = default; UnlimitedHandleResource(const UnlimitedHandleResource&) = delete; UnlimitedHandleResource& operator=(const UnlimitedHandleResource&) = delete; THandle Allocate(std::shared_ptr structure); std::shared_ptr Get(THandle handle); /* Returns structure previously at that handle (or nullptr if none) */ std::shared_ptr Free(THandle handle); void ResetHandles() override; /* Calls func(THandle, TStruct*) for each handle. Note this holds the * global lock for the entirety of execution. */ template void ForEach(Functor func); private: std::vector> m_structures; wpi::mutex m_handleMutex; }; template THandle UnlimitedHandleResource::Allocate( std::shared_ptr structure) { std::scoped_lock lock(m_handleMutex); size_t i; for (i = 0; i < m_structures.size(); i++) { if (m_structures[i] == nullptr) { m_structures[i] = structure; return static_cast(createHandle(i, enumValue, m_version)); } } if (i >= INT16_MAX) return HAL_kInvalidHandle; m_structures.push_back(structure); return static_cast( createHandle(static_cast(i), enumValue, m_version)); } template std::shared_ptr UnlimitedHandleResource::Get(THandle handle) { int16_t index = getHandleTypedIndex(handle, enumValue, m_version); std::scoped_lock lock(m_handleMutex); if (index < 0 || index >= static_cast(m_structures.size())) return nullptr; return m_structures[index]; } template std::shared_ptr UnlimitedHandleResource::Free(THandle handle) { int16_t index = getHandleTypedIndex(handle, enumValue, m_version); std::scoped_lock lock(m_handleMutex); if (index < 0 || index >= static_cast(m_structures.size())) return nullptr; return std::move(m_structures[index]); } template void UnlimitedHandleResource::ResetHandles() { { std::scoped_lock lock(m_handleMutex); for (size_t i = 0; i < m_structures.size(); i++) { m_structures[i].reset(); } } HandleBase::ResetHandles(); } template template void UnlimitedHandleResource::ForEach( Functor func) { std::scoped_lock lock(m_handleMutex); size_t i; for (i = 0; i < m_structures.size(); i++) { if (m_structures[i] != nullptr) { func(static_cast(createHandle(i, enumValue, m_version)), m_structures[i].get()); } } } } // namespace hal