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