jerrym | f157933 | 2013-02-07 01:56:28 +0000 | [diff] [blame] | 1 | /*----------------------------------------------------------------------------*/
|
| 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 |
|
| 11 | ReentrantSemaphore 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 | */
|
| 18 | Resource::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 | */
|
| 52 | Resource::~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 | */
|
| 62 | UINT32 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 | */
|
| 82 | UINT32 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 | */
|
| 105 | void 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 | }
|