diff --git a/wpilibc/src/main/native/cpp/DriverStation.cpp b/wpilibc/src/main/native/cpp/DriverStation.cpp index df34738165..ef8a586f98 100644 --- a/wpilibc/src/main/native/cpp/DriverStation.cpp +++ b/wpilibc/src/main/native/cpp/DriverStation.cpp @@ -139,22 +139,22 @@ void DriverStation::ReportError(bool isError, int32_t code, * @return The state of the joystick button. */ bool DriverStation::GetStickButton(int stick, int button) { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return false; } - if (button == 0) { + if (button <= 0) { ReportJoystickUnpluggedError( "ERROR: Button indexes begin at 1 in WPILib for C++ and Java"); return false; } + std::unique_lock lock(m_cacheDataMutex); if (button > m_joystickButtons[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); ReportJoystickUnpluggedWarning( - "Joystick Button missing, check if all controllers are " - "plugged in"); + "Joystick Button missing, check if all controllers are plugged in"); return false; } @@ -170,22 +170,22 @@ bool DriverStation::GetStickButton(int stick, int button) { * @return Whether the joystick button was pressed since the last check. */ bool DriverStation::GetStickButtonPressed(int stick, int button) { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return false; } - if (button == 0) { + if (button <= 0) { ReportJoystickUnpluggedError( "ERROR: Button indexes begin at 1 in WPILib for C++ and Java"); return false; } + std::unique_lock lock(m_cacheDataMutex); if (button > m_joystickButtons[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); ReportJoystickUnpluggedWarning( - "Joystick Button missing, check if all controllers are " - "plugged in"); + "Joystick Button missing, check if all controllers are plugged in"); return false; } @@ -207,7 +207,7 @@ bool DriverStation::GetStickButtonPressed(int stick, int button) { * @return Whether the joystick button was released since the last check. */ bool DriverStation::GetStickButtonReleased(int stick, int button) { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return false; } @@ -216,13 +216,13 @@ bool DriverStation::GetStickButtonReleased(int stick, int button) { "ERROR: Button indexes begin at 1 in WPILib for C++ and Java"); return false; } + std::unique_lock lock(m_cacheDataMutex); if (button > m_joystickButtons[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); ReportJoystickUnpluggedWarning( - "Joystick Button missing, check if all controllers are " - "plugged in"); + "Joystick Button missing, check if all controllers are plugged in"); return false; } @@ -245,20 +245,21 @@ bool DriverStation::GetStickButtonReleased(int stick, int button) { * @return The value of the axis on the joystick. */ double DriverStation::GetStickAxis(int stick, int axis) { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); - return 0; + return 0.0; } + if (axis >= HAL_kMaxJoystickAxes) { + wpi_setWPIError(BadJoystickAxis); + return 0.0; + } + std::unique_lock lock(m_cacheDataMutex); if (axis >= m_joystickAxes[stick].count) { // Unlock early so error printing isn't locked. - m_cacheDataMutex.unlock(); - lock.release(); - if (axis >= HAL_kMaxJoystickAxes) - wpi_setWPIError(BadJoystickAxis); - else - ReportJoystickUnpluggedWarning( - "Joystick Axis missing, check if all controllers are plugged in"); + lock.unlock(); + ReportJoystickUnpluggedWarning( + "Joystick Axis missing, check if all controllers are plugged in"); return 0.0; } @@ -271,19 +272,21 @@ double DriverStation::GetStickAxis(int stick, int axis) { * @return the angle of the POV in degrees, or -1 if the POV is not pressed. */ int DriverStation::GetStickPOV(int stick, int pov) { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return -1; } + if (pov >= HAL_kMaxJoystickPOVs) { + wpi_setWPIError(BadJoystickAxis); + return -1; + } + std::unique_lock lock(m_cacheDataMutex); if (pov >= m_joystickPOVs[stick].count) { // Unlock early so error printing isn't locked. lock.unlock(); - if (pov >= HAL_kMaxJoystickPOVs) - wpi_setWPIError(BadJoystickAxis); - else - ReportJoystickUnpluggedWarning( - "Joystick POV missing, check if all controllers are plugged in"); + ReportJoystickUnpluggedWarning( + "Joystick POV missing, check if all controllers are plugged in"); return -1; } @@ -297,10 +300,11 @@ int DriverStation::GetStickPOV(int stick, int pov) { * @return The state of the buttons on the joystick. */ int DriverStation::GetStickButtons(int stick) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return 0; } + std::lock_guard lock(m_cacheDataMutex); return m_joystickButtons[stick].buttons; } @@ -312,10 +316,11 @@ int DriverStation::GetStickButtons(int stick) const { * @return The number of axes on the indicated joystick */ int DriverStation::GetStickAxisCount(int stick) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return 0; } + std::lock_guard lock(m_cacheDataMutex); return m_joystickAxes[stick].count; } @@ -327,10 +332,11 @@ int DriverStation::GetStickAxisCount(int stick) const { * @return The number of POVs on the indicated joystick */ int DriverStation::GetStickPOVCount(int stick) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return 0; } + std::lock_guard lock(m_cacheDataMutex); return m_joystickPOVs[stick].count; } @@ -342,10 +348,11 @@ int DriverStation::GetStickPOVCount(int stick) const { * @return The number of buttons on the indicated joystick */ int DriverStation::GetStickButtonCount(int stick) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return 0; } + std::lock_guard lock(m_cacheDataMutex); return m_joystickButtons[stick].count; } @@ -357,10 +364,11 @@ int DriverStation::GetStickButtonCount(int stick) const { * @return A boolean that is true if the controller is an xbox controller. */ bool DriverStation::GetJoystickIsXbox(int stick) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return false; } + std::lock_guard lock(m_cacheDataMutex); return static_cast(m_joystickDescriptor[stick].isXbox); } @@ -372,10 +380,11 @@ bool DriverStation::GetJoystickIsXbox(int stick) const { * @return The HID type of joystick at the given port */ int DriverStation::GetJoystickType(int stick) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return -1; } + std::lock_guard lock(m_cacheDataMutex); return static_cast(m_joystickDescriptor[stick].type); } @@ -387,12 +396,12 @@ int DriverStation::GetJoystickType(int stick) const { * @return The name of the joystick at the given port */ std::string DriverStation::GetJoystickName(int stick) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); } + std::lock_guard lock(m_cacheDataMutex); - std::string retVal(m_joystickDescriptor[stick].name); - return retVal; + return m_joystickDescriptor[stick].name; } /** @@ -402,10 +411,11 @@ std::string DriverStation::GetJoystickName(int stick) const { * @return What type of axis the axis is reporting to be */ int DriverStation::GetJoystickAxisType(int stick, int axis) const { - if (stick >= kJoystickPorts) { + if (stick < 0 || stick >= kJoystickPorts) { wpi_setWPIError(BadJoystickIndex); return -1; } + std::lock_guard lock(m_cacheDataMutex); return m_joystickDescriptor[stick].axisTypes[axis]; } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java index f6c847d077..c3d5bdc811 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DriverStation.java @@ -152,7 +152,7 @@ public class DriverStation implements RobotState.Interface { private Thread m_thread; private volatile boolean m_threadKeepAlive = true; - private final Object m_cacheDataMutex; + private final ReentrantLock m_cacheDataMutex = new ReentrantLock(); private final Lock m_waitForDataMutex; private final Condition m_waitForDataCond; @@ -189,7 +189,6 @@ public class DriverStation implements RobotState.Interface { m_waitForDataMutex = new ReentrantLock(); m_waitForDataCond = m_waitForDataMutex.newCondition(); - m_cacheDataMutex = new Object(); for (int i = 0; i < kJoystickPorts; i++) { m_joystickButtons[i] = new HALJoystickButtons(); m_joystickAxes[i] = new HALJoystickAxes(HAL.kMaxJoystickAxes); @@ -304,28 +303,28 @@ public class DriverStation implements RobotState.Interface { * @return The state of the joystick button. */ public boolean getStickButton(final int stick, final int button) { + if (stick < 0 || stick >= kJoystickPorts) { + throw new RuntimeException("Joystick index is out of range, should be 0-3"); + } if (button <= 0) { reportJoystickUnpluggedError("Button indexes begin at 1 in WPILib for C++ and Java\n"); return false; } - if (stick < 0 || stick >= kJoystickPorts) { - throw new RuntimeException("Joystick index is out of range, should be 0-3"); - } - boolean error = false; - boolean retVal = false; - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { if (button > m_joystickButtons[stick].m_count) { - error = true; - retVal = false; - } else { - retVal = (m_joystickButtons[stick].m_buttons & 1 << (button - 1)) != 0; + // Unlock early so error printing isn't locked. + m_cacheDataMutex.unlock(); + reportJoystickUnpluggedWarning("Joystick Button " + button + " on port " + stick + + " not available, check if controller is plugged in"); + } + + return (m_joystickButtons[stick].m_buttons & 1 << (button - 1)) != 0; + } finally { + if (m_cacheDataMutex.isHeldByCurrentThread()) { + m_cacheDataMutex.unlock(); } } - if (error) { - reportJoystickUnpluggedWarning("Joystick Button " + button + " on port " + stick - + " not available, check if controller is plugged in"); - } - return retVal; } /** @@ -391,26 +390,26 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - if (axis < 0 || axis >= HAL.kMaxJoystickAxes) { + if (axis >= HAL.kMaxJoystickAxes) { throw new RuntimeException("Joystick axis is out of range"); } - boolean error = false; - double retVal = 0.0; - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { if (axis >= m_joystickAxes[stick].m_count) { - // set error - error = true; - retVal = 0.0; - } else { - retVal = m_joystickAxes[stick].m_axes[axis]; + // Unlock early so error printing isn't locked. + m_cacheDataMutex.unlock(); + reportJoystickUnpluggedWarning("Joystick axis " + axis + " on port " + stick + + " not available, check if controller is plugged in"); + return 0.0; + } + + return m_joystickAxes[stick].m_axes[axis]; + } finally { + if (m_cacheDataMutex.isHeldByCurrentThread()) { + m_cacheDataMutex.unlock(); } } - if (error) { - reportJoystickUnpluggedWarning("Joystick axis " + axis + " on port " + stick - + " not available, check if controller is plugged in"); - } - return retVal; } /** @@ -422,24 +421,25 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - if (pov < 0 || pov >= HAL.kMaxJoystickPOVs) { + if (pov >= HAL.kMaxJoystickPOVs) { throw new RuntimeException("Joystick POV is out of range"); } - boolean error = false; - int retVal = -1; - synchronized (m_cacheDataMutex) { + + m_cacheDataMutex.lock(); + try { if (pov >= m_joystickPOVs[stick].m_count) { - error = true; - retVal = -1; - } else { - retVal = m_joystickPOVs[stick].m_povs[pov]; + // Unlock early so error printing isn't locked. + m_cacheDataMutex.unlock(); + reportJoystickUnpluggedWarning("Joystick POV " + pov + " on port " + stick + + " not available, check if controller is plugged in"); + } + } finally { + if (m_cacheDataMutex.isHeldByCurrentThread()) { + m_cacheDataMutex.unlock(); } } - if (error) { - reportJoystickUnpluggedWarning("Joystick POV " + pov + " on port " + stick - + " not available, check if controller is plugged in"); - } - return retVal; + + return m_joystickPOVs[stick].m_povs[pov]; } /** @@ -452,8 +452,12 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-3"); } - synchronized (m_cacheDataMutex) { + + m_cacheDataMutex.lock(); + try { return m_joystickButtons[stick].m_buttons; + } finally { + m_cacheDataMutex.unlock(); } } @@ -467,8 +471,12 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - synchronized (m_cacheDataMutex) { + + m_cacheDataMutex.lock(); + try { return m_joystickAxes[stick].m_count; + } finally { + m_cacheDataMutex.unlock(); } } @@ -482,8 +490,12 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - synchronized (m_cacheDataMutex) { + + m_cacheDataMutex.lock(); + try { return m_joystickPOVs[stick].m_count; + } finally { + m_cacheDataMutex.unlock(); } } @@ -497,8 +509,12 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - synchronized (m_cacheDataMutex) { + + m_cacheDataMutex.lock(); + try { return m_joystickButtons[stick].m_count; + } finally { + m_cacheDataMutex.unlock(); } } @@ -512,23 +528,13 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - boolean error = false; - boolean retVal = false; - synchronized (m_cacheDataMutex) { - // TODO: Remove this when calling for descriptor on empty stick no longer - // crashes - if (1 > m_joystickButtons[stick].m_count && 1 > m_joystickAxes[stick].m_count) { - error = true; - retVal = false; - } else if (HAL.getJoystickIsXbox((byte) stick) == 1) { - retVal = true; - } + + m_cacheDataMutex.lock(); + try { + return HAL.getJoystickIsXbox((byte) stick) == 1; + } finally { + m_cacheDataMutex.unlock(); } - if (error) { - reportJoystickUnpluggedWarning("Joystick on port " + stick - + " not available, check if controller is plugged in"); - } - return retVal; } /** @@ -541,23 +547,13 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - boolean error = false; - int retVal = -1; - synchronized (m_cacheDataMutex) { - // TODO: Remove this when calling for descriptor on empty stick no longer - // crashes - if (1 > m_joystickButtons[stick].m_count && 1 > m_joystickAxes[stick].m_count) { - error = true; - retVal = -1; - } else { - retVal = HAL.getJoystickType((byte) stick); - } + + m_cacheDataMutex.lock(); + try { + return HAL.getJoystickType((byte) stick); + } finally { + m_cacheDataMutex.unlock(); } - if (error) { - reportJoystickUnpluggedWarning("Joystick on port " + stick - + " not available, check if controller is plugged in"); - } - return retVal; } /** @@ -570,23 +566,13 @@ public class DriverStation implements RobotState.Interface { if (stick < 0 || stick >= kJoystickPorts) { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - boolean error = false; - String retVal = ""; - synchronized (m_cacheDataMutex) { - // TODO: Remove this when calling for descriptor on empty stick no longer - // crashes - if (1 > m_joystickButtons[stick].m_count && 1 > m_joystickAxes[stick].m_count) { - error = true; - retVal = ""; - } else { - retVal = HAL.getJoystickName((byte) stick); - } + + m_cacheDataMutex.lock(); + try { + return HAL.getJoystickName((byte) stick); + } finally { + m_cacheDataMutex.unlock(); } - if (error) { - reportJoystickUnpluggedWarning("Joystick on port " + stick - + " not available, check if controller is plugged in"); - } - return retVal; } /** @@ -601,11 +587,12 @@ public class DriverStation implements RobotState.Interface { throw new RuntimeException("Joystick index is out of range, should be 0-5"); } - int retVal = -1; - synchronized (m_cacheDataMutex) { - retVal = HAL.getJoystickAxisType((byte) stick, (byte) axis); + m_cacheDataMutex.lock(); + try { + return HAL.getJoystickAxisType((byte) stick, (byte) axis); + } finally { + m_cacheDataMutex.unlock(); } - return retVal; } /** @@ -728,8 +715,11 @@ public class DriverStation implements RobotState.Interface { * @return the game specific message */ public String getGameSpecificMessage() { - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { return m_matchInfo.gameSpecificMessage; + } finally { + m_cacheDataMutex.unlock(); } } @@ -739,8 +729,11 @@ public class DriverStation implements RobotState.Interface { * @return the event name */ public String getEventName() { - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { return m_matchInfo.eventName; + } finally { + m_cacheDataMutex.unlock(); } } @@ -751,8 +744,11 @@ public class DriverStation implements RobotState.Interface { */ public MatchType getMatchType() { int matchType; - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { matchType = m_matchInfo.matchType; + } finally { + m_cacheDataMutex.unlock(); } switch (matchType) { case 1: @@ -772,8 +768,11 @@ public class DriverStation implements RobotState.Interface { * @return the match number */ public int getMatchNumber() { - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { return m_matchInfo.matchNumber; + } finally { + m_cacheDataMutex.unlock(); } } @@ -783,8 +782,11 @@ public class DriverStation implements RobotState.Interface { * @return the replay number */ public int getReplayNumber() { - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { return m_matchInfo.replayNumber; + } finally { + m_cacheDataMutex.unlock(); } } @@ -1036,7 +1038,8 @@ public class DriverStation implements RobotState.Interface { updateControlWord(true); // lock joystick mutex to swap cache data - synchronized (m_cacheDataMutex) { + m_cacheDataMutex.lock(); + try { for (int i = 0; i < kJoystickPorts; i++) { // If buttons weren't pressed and are now, set flags in m_buttonsPressed m_joystickButtonsPressed[i].m_buttons |= @@ -1063,6 +1066,8 @@ public class DriverStation implements RobotState.Interface { MatchInfoData currentInfo = m_matchInfo; m_matchInfo = m_matchInfoCache; m_matchInfoCache = currentInfo; + } finally { + m_cacheDataMutex.unlock(); } m_waitForDataMutex.lock();