001 /*----------------------------------------------------------------------------*/ 002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */ 003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 004 /* must be accompanied by the FIRST BSD license file in the root directory of */ 005 /* the project. */ 006 /*----------------------------------------------------------------------------*/ 007 008 package edu.wpi.first.wpilibj; 009 010 import edu.wpi.first.wpilibj.util.AllocationException; 011 import edu.wpi.first.wpilibj.util.CheckedAllocationException; 012 013 /** 014 * Track resources in the program. 015 * The Resource class is a convenient way of keeping track of allocated arbitrary resources 016 * in the program. Resources are just indicies that have an lower and upper bound that are 017 * tracked by this class. In the library they are used for tracking allocation of hardware channels 018 * but this is purely arbitrary. The resource class does not do any actual allocation, but 019 * simply tracks if a given index is currently in use. 020 * 021 * WARNING: this should only be statically allocated. When the program loads into memory all the 022 * static constructors are called. At that time a linked list of all the "Resources" is created. 023 * Then when the program actually starts - in the Robot constructor, all resources are initialized. 024 * This ensures that the program is restartable in memory without having to unload/reload. 025 */ 026 public class Resource { 027 028 private static Resource m_resourceList = null; 029 private final boolean m_numAllocated[]; 030 private final int m_size; 031 private final Resource m_nextResource; 032 033 /** 034 * Clears all allocated resources 035 */ 036 public static void restartProgram() { 037 for (Resource r = Resource.m_resourceList; r != null; r = r.m_nextResource) { 038 for (int i = 0; i < r.m_size; i++) { 039 r.m_numAllocated[i] = false; 040 } 041 } 042 } 043 044 /** 045 * Allocate storage for a new instance of Resource. 046 * Allocate a bool array of values that will get initialized to indicate that no resources 047 * have been allocated yet. The indicies of the resources are 0..size-1. 048 * 049 * @param size The number of blocks to allocate 050 */ 051 public Resource(final int size) { 052 m_size = size; 053 m_numAllocated = new boolean[m_size]; 054 for (int i = 0; i < m_size; i++) { 055 m_numAllocated[i] = false; 056 } 057 m_nextResource = Resource.m_resourceList; 058 Resource.m_resourceList = this; 059 } 060 061 /** 062 * Allocate a resource. 063 * When a resource is requested, mark it allocated. In this case, a free resource value 064 * within the range is located and returned after it is marked allocated. 065 * 066 * @return The index of the allocated block. 067 * @throws CheckedAllocationException If there are no resources available to be allocated. 068 */ 069 public int allocate() throws CheckedAllocationException { 070 for (int i = 0; i < m_size; i++) { 071 if (m_numAllocated[i] == false) { 072 m_numAllocated[i] = true; 073 return i; 074 } 075 } 076 throw new CheckedAllocationException("No available resources"); 077 } 078 079 /** 080 * Allocate a specific resource value. 081 * The user requests a specific resource value, i.e. channel number and it is verified 082 * unallocated, then returned. 083 * 084 * @param index The resource to allocate 085 * @return The index of the allocated block 086 * @throws CheckedAllocationException If there are no resources available to be allocated. 087 */ 088 public int allocate(final int index) throws CheckedAllocationException { 089 if (index >= m_size) { 090 throw new CheckedAllocationException("Index " + index + " out of range"); 091 } 092 if (m_numAllocated[index] == true) { 093 throw new CheckedAllocationException("Resource at index " + index + " already allocated"); 094 } 095 m_numAllocated[index] = true; 096 return index; 097 } 098 099 /** 100 * Free an allocated resource. 101 * After a resource is no longer needed, for example a destructor is called for a channel assignment 102 * class, Free will release the resource value so it can be reused somewhere else in the program. 103 * 104 * @param index The index of the resource to free. 105 */ 106 public void free(final int index) { 107 if (m_numAllocated[index] == false) 108 throw new AllocationException("No resource available to be freed"); 109 m_numAllocated[index] = false; 110 } 111 }