blob: 3e13d6369d831390ff689a42d0b0cabc6763573c [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
Brian Silverman1a675112016-02-20 20:42:49 -05002/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
Brian Silverman26e4e522015-12-17 01:56:40 -05003/* Open Source Software - may be modified and shared by FRC teams. The code */
Brian Silverman1a675112016-02-20 20:42:49 -05004/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
Brian Silverman26e4e522015-12-17 01:56:40 -05006/*----------------------------------------------------------------------------*/
7
8#include "HAL/cpp/Resource.hpp"
9#include "HAL/Errors.hpp"
10#include <cstddef>
11#include "HAL/cpp/priority_mutex.h"
12
13namespace hal {
14
15priority_recursive_mutex Resource::m_createLock;
16
17/**
18 * Allocate storage for a new instance of Resource.
19 * Allocate a bool array of values that will get initialized to indicate that no resources
20 * have been allocated yet. The indicies of the resources are [0 .. elements - 1].
21 */
22Resource::Resource(uint32_t elements) {
23 std::lock_guard<priority_recursive_mutex> sync(m_createLock);
24 m_isAllocated = std::vector<bool>(elements, false);
25}
26
27/**
28 * Factory method to create a Resource allocation-tracker *if* needed.
29 *
30 * @param r -- address of the caller's Resource pointer. If *r == NULL, this
31 * will construct a Resource and make *r point to it. If *r != NULL, i.e.
32 * the caller already has a Resource instance, this won't do anything.
33 * @param elements -- the number of elements for this Resource allocator to
34 * track, that is, it will allocate resource numbers in the range
35 * [0 .. elements - 1].
36 */
37/*static*/ void Resource::CreateResourceObject(Resource **r, uint32_t elements)
38{
39 std::lock_guard<priority_recursive_mutex> sync(m_createLock);
40 if (*r == NULL)
41 {
42 *r = new Resource(elements);
43 }
44}
45
46/**
47 * Allocate a resource.
48 * When a resource is requested, mark it allocated. In this case, a free resource value
49 * within the range is located and returned after it is marked allocated.
50 */
51uint32_t Resource::Allocate(const char *resourceDesc)
52{
53 std::lock_guard<priority_recursive_mutex> sync(m_allocateLock);
54 for (uint32_t i=0; i < m_isAllocated.size(); i++)
55 {
56 if (!m_isAllocated[i])
57 {
58 m_isAllocated[i] = true;
59 return i;
60 }
61 }
62 // TODO: wpi_setWPIErrorWithContext(NoAvailableResources, resourceDesc);
63 return ~0ul;
64}
65
66/**
67 * Allocate a specific resource value.
68 * The user requests a specific resource value, i.e. channel number and it is verified
69 * unallocated, then returned.
70 */
71uint32_t Resource::Allocate(uint32_t index, const char *resourceDesc)
72{
73 std::lock_guard<priority_recursive_mutex> sync(m_allocateLock);
74 if (index >= m_isAllocated.size())
75 {
76 // TODO: wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, resourceDesc);
77 return ~0ul;
78 }
79 if ( m_isAllocated[index] )
80 {
81 // TODO: wpi_setWPIErrorWithContext(ResourceAlreadyAllocated, resourceDesc);
82 return ~0ul;
83 }
84 m_isAllocated[index] = true;
85 return index;
86}
87
88
89/**
90 * Free an allocated resource.
91 * After a resource is no longer needed, for example a destructor is called for a channel assignment
92 * class, Free will release the resource value so it can be reused somewhere else in the program.
93 */
94void Resource::Free(uint32_t index)
95{
96 std::lock_guard<priority_recursive_mutex> sync(m_allocateLock);
97 if (index == ~0ul) return;
98 if (index >= m_isAllocated.size())
99 {
100 // TODO: wpi_setWPIError(NotAllocated);
101 return;
102 }
103 if (!m_isAllocated[index])
104 {
105 // TODO: wpi_setWPIError(NotAllocated);
106 return;
107 }
108 m_isAllocated[index] = false;
109}
110
111} // namespace hal