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