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}