001/* 002 * DCCppRegisterManager.java 003 */ 004package jmri.jmrix.dccpp; 005 006import org.slf4j.Logger; 007import org.slf4j.LoggerFactory; 008 009/** 010 * Defines and Manages the Registers (~ slots) for DCC++ Base Station 011 * 012 * @author Mark Underwood Copyright (C) 2015 013 * @author Harald Barth Copyright (C) 2019 014 * 015 */ 016 017/* A few notes on implementation 018 * 019 * This class is used by the DCCppCommandStation to allocate/free and keep 020 * track of the registers in the BaseStation. This is assuming the BaseStation 021 * doesn't provide its own method of allocating registers. It would be better 022 * if the BaseStation handled this, since there may be more than just JMRI 023 * asking for slots. 024 */ 025public class DCCppRegisterManager { 026 027 protected int maxMainRegisters = 0; 028 protected DCCppRegister registers[]; 029 030 // Constructors 031 public DCCppRegisterManager(int maxMainRegisters) { 032 log.debug("DCCppRegisterManager({}) called.", maxMainRegisters); 033 this.maxMainRegisters = maxMainRegisters; 034 registers = new DCCppRegister[maxMainRegisters]; 035 for (int i = 0; i < maxMainRegisters; i++) { 036 registers[i] = new DCCppRegister(); 037 } 038 } 039 040 public DCCppRegisterManager() { 041 this(DCCppConstants.MAX_MAIN_REGISTERS); 042 } 043 044 // Member functions 045 public int requestRegister(int addr) { 046 int free = DCCppConstants.NO_REGISTER_FREE; 047 048 for (int i = 0; i < maxMainRegisters; i++) { 049 if (registers[i].getAddress() == addr) { 050 registers[i].allocate(); 051 log.debug("requestRegister({}) returns {}", addr, i); 052 return (i); 053 } 054 // This might be a free spot 055 if (free == DCCppConstants.NO_REGISTER_FREE && registers[i].isFree()) { 056 free = i; 057 } 058 } 059 // If we've made it here, there isn't a register that already matches. 060 // Look if we found a free one on the way through the list above 061 // if not, there is no available slot. Bummer. 062 if (free != DCCppConstants.NO_REGISTER_FREE) { 063 registers[free].allocate(); 064 registers[free].setAddress(addr); 065 } 066 log.debug("requestRegister({}) returns {}", addr, free); 067 return (free); 068 } 069 070 public void releaseRegister(int addr) { 071 for (int i = 0; i < maxMainRegisters; i++) { 072 if (registers[i].getAddress() == addr) { 073 registers[i].release(); 074 } 075 } 076 } 077 078 // NOTE: queryRegisterNum does not increment the use count. 079 public int getRegisterNum(int addr) { 080 for (int i = 0; i < maxMainRegisters; i++) { 081 if (registers[i].getAddress() == addr) { 082 return (i + 1); 083 } 084 } 085 // Optional: If a nonexistent register is requested, create one? 086 return (DCCppConstants.NO_REGISTER_FREE); 087 } 088 089 public int getRegisterAddress(int num) { 090 return (registers[num - 1].getAddress()); 091 } 092 /* 093 * We need to register for logging 094 */ 095 private final static Logger log = LoggerFactory.getLogger(DCCppRegisterManager.class); 096 097} 098 099class DCCppRegister { 100 101 private int user_count; 102 private int address; 103 104 public DCCppRegister() { 105 user_count = 0; 106 address = DCCppConstants.REGISTER_UNALLOCATED; 107 } 108 109 public int getUserCount() { 110 return (user_count); 111 } 112 113 public void setUserCount(int i) { 114 user_count = i; 115 } // Don't use this... 116 117 public void incUserCount() { 118 user_count++; 119 } 120 121 public void decUserCount() { 122 if (user_count > 0) { 123 user_count--; 124 } 125 if (user_count == 0) { 126 address = DCCppConstants.REGISTER_UNALLOCATED; 127 } 128 } 129 130 public int getAddress() { 131 return (address); 132 } 133 134 public void setAddress(int a) { 135 address = a; 136 } 137 138 public boolean isAllocated() { 139 return (user_count > 0); 140 } 141 142 public boolean isFree() { 143 return (user_count == 0); 144 } 145 146 public void allocate() { 147 this.incUserCount(); 148 } 149 150 public void release() { 151 this.decUserCount(); 152 } 153}