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