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.simulation;
006
007/** Manages simulation callbacks; each object is associated with a callback. */
008public class CallbackStore implements AutoCloseable {
009  /** <b>Note: This interface is for simulation classes only. It should not be used by teams!</b> */
010  @SuppressWarnings("PMD.ImplicitFunctionalInterface")
011  interface CancelCallbackFunc {
012    void cancel(int index, int uid);
013  }
014
015  /** <b>Note: This interface is for simulation classes only. It should not be used by teams!</b> */
016  @SuppressWarnings("PMD.ImplicitFunctionalInterface")
017  interface CancelCallbackChannelFunc {
018    void cancel(int index, int channel, int uid);
019  }
020
021  /** <b>Note: This interface is for simulation classes only. It should not be used by teams!</b> */
022  @SuppressWarnings("PMD.ImplicitFunctionalInterface")
023  interface CancelCallbackNoIndexFunc {
024    void cancel(int uid);
025  }
026
027  /**
028   * Constructs an empty CallbackStore. This constructor is to allow 3rd party sim providers (eg
029   * vendors) to subclass this class (without needing provide dummy constructing parameters) so that
030   * the register methods of their sim classes can return CallbackStores like the builtin sims.
031   * <b>Note: It should not be called by teams that are just using sims!</b>
032   */
033  protected CallbackStore() {
034    this.m_cancelType = -1;
035    this.m_index = -1;
036    this.m_uid = -1;
037    this.m_cancelCallback = null;
038    this.m_cancelCallbackChannel = null;
039  }
040
041  /**
042   * <b>Note: This constructor is for simulation classes only. It should not be called by teams!</b>
043   *
044   * @param index TODO
045   * @param uid TODO
046   * @param ccf TODO
047   */
048  public CallbackStore(int index, int uid, CancelCallbackFunc ccf) {
049    this.m_cancelType = kNormalCancel;
050    this.m_index = index;
051    this.m_uid = uid;
052    this.m_cancelCallback = ccf;
053  }
054
055  /**
056   * <b>Note: This constructor is for simulation classes only. It should not be called by teams!</b>
057   *
058   * @param index TODO
059   * @param channel TODO
060   * @param uid TODO
061   * @param ccf TODO
062   */
063  public CallbackStore(int index, int channel, int uid, CancelCallbackChannelFunc ccf) {
064    this.m_cancelType = kChannelCancel;
065    this.m_index = index;
066    this.m_uid = uid;
067    this.m_channel = channel;
068    this.m_cancelCallbackChannel = ccf;
069  }
070
071  /**
072   * <b>Note: This constructor is for simulation classes only. It should not be called by teams!</b>
073   *
074   * @param uid TODO
075   * @param ccf TODO
076   */
077  public CallbackStore(int uid, CancelCallbackNoIndexFunc ccf) {
078    this.m_cancelType = kNoIndexCancel;
079    this.m_uid = uid;
080    this.m_cancelCallbackNoIndex = ccf;
081  }
082
083  private int m_index;
084  private int m_channel;
085  private final int m_uid;
086  private CancelCallbackFunc m_cancelCallback;
087  private CancelCallbackChannelFunc m_cancelCallbackChannel;
088  private CancelCallbackNoIndexFunc m_cancelCallbackNoIndex;
089  private static final int kAlreadyCancelled = -1;
090  private static final int kNormalCancel = 0;
091  private static final int kChannelCancel = 1;
092  private static final int kNoIndexCancel = 2;
093  private int m_cancelType;
094
095  /** Cancel the callback associated with this object. */
096  @Override
097  public void close() {
098    switch (m_cancelType) {
099      case kAlreadyCancelled -> {
100        // Already cancelled so do nothing so that close() is idempotent.
101        return;
102      }
103      case kNormalCancel -> m_cancelCallback.cancel(m_index, m_uid);
104      case kChannelCancel -> m_cancelCallbackChannel.cancel(m_index, m_channel, m_uid);
105      case kNoIndexCancel -> m_cancelCallbackNoIndex.cancel(m_uid);
106      default -> {
107        assert false;
108      }
109    }
110    m_cancelType = kAlreadyCancelled;
111  }
112}