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