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