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.internal;
006
007import edu.wpi.first.hal.DriverStationJNI;
008import edu.wpi.first.util.WPIUtilJNI;
009import edu.wpi.first.wpilibj.DriverStation;
010import java.util.concurrent.atomic.AtomicBoolean;
011
012/*
013 * For internal use only.
014 */
015public class DriverStationModeThread implements AutoCloseable {
016  private final AtomicBoolean m_keepAlive = new AtomicBoolean();
017  private final Thread m_thread;
018
019  private boolean m_userInDisabled;
020  private boolean m_userInAutonomous;
021  private boolean m_userInTeleop;
022  private boolean m_userInTest;
023
024  /** Internal use only. */
025  public DriverStationModeThread() {
026    m_keepAlive.set(true);
027    m_thread = new Thread(this::run, "DriverStationMode");
028    m_thread.start();
029  }
030
031  private void run() {
032    int handle = WPIUtilJNI.createEvent(false, false);
033    DriverStationJNI.provideNewDataEventHandle(handle);
034
035    while (m_keepAlive.get()) {
036      try {
037        WPIUtilJNI.waitForObjectTimeout(handle, 0.1);
038      } catch (InterruptedException e) {
039        DriverStationJNI.removeNewDataEventHandle(handle);
040        WPIUtilJNI.destroyEvent(handle);
041        Thread.currentThread().interrupt();
042        return;
043      }
044      DriverStation.refreshData();
045      if (m_userInDisabled) {
046        DriverStationJNI.observeUserProgramDisabled();
047      }
048      if (m_userInAutonomous) {
049        DriverStationJNI.observeUserProgramAutonomous();
050      }
051      if (m_userInTeleop) {
052        DriverStationJNI.observeUserProgramTeleop();
053      }
054      if (m_userInTest) {
055        DriverStationJNI.observeUserProgramTest();
056      }
057    }
058
059    DriverStationJNI.removeNewDataEventHandle(handle);
060    WPIUtilJNI.destroyEvent(handle);
061  }
062
063  /**
064   * Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
065   * purposes only.
066   *
067   * @param entering If true, starting disabled code; if false, leaving disabled code
068   */
069  public void inDisabled(boolean entering) {
070    m_userInDisabled = entering;
071  }
072
073  /**
074   * Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
075   * purposes only.
076   *
077   * @param entering If true, starting autonomous code; if false, leaving autonomous code
078   */
079  public void inAutonomous(boolean entering) {
080    m_userInAutonomous = entering;
081  }
082
083  /**
084   * Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
085   * purposes only.
086   *
087   * @param entering If true, starting teleop code; if false, leaving teleop code
088   */
089  public void inTeleop(boolean entering) {
090    m_userInTeleop = entering;
091  }
092
093  /**
094   * Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
095   * purposes only.
096   *
097   * @param entering If true, starting test code; if false, leaving test code
098   */
099  public void inTest(boolean entering) {
100    m_userInTest = entering;
101  }
102
103  @Override
104  public void close() {
105    m_keepAlive.set(false);
106    try {
107      m_thread.join();
108    } catch (InterruptedException e) {
109      Thread.currentThread().interrupt();
110    }
111  }
112}