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.networktables; 006 007import java.util.EnumSet; 008 009/** 010 * Event listener poller. This queues events matching the specified mask. Code using the listener 011 * must periodically call readQueue() to read the events. 012 */ 013public final class NetworkTableListenerPoller implements AutoCloseable { 014 /** 015 * Construct a topic listener poller. 016 * 017 * @param inst Instance 018 */ 019 public NetworkTableListenerPoller(NetworkTableInstance inst) { 020 m_inst = inst; 021 m_handle = NetworkTablesJNI.createListenerPoller(inst.getHandle()); 022 } 023 024 /** 025 * Start listening to topic changes for topics with names that start with any of the given 026 * prefixes. This creates a corresponding internal subscriber with the lifetime of the listener. 027 * 028 * @param prefixes Topic name string prefixes 029 * @param eventKinds set of event kinds to listen to 030 * @return Listener handle 031 */ 032 public int addListener(String[] prefixes, EnumSet<NetworkTableEvent.Kind> eventKinds) { 033 return NetworkTablesJNI.addListener(m_handle, prefixes, eventKinds); 034 } 035 036 /** 037 * Start listening to changes to a particular topic. This creates a corresponding internal 038 * subscriber with the lifetime of the listener. 039 * 040 * @param topic Topic 041 * @param eventKinds set of event kinds to listen to 042 * @return Listener handle 043 */ 044 public int addListener(Topic topic, EnumSet<NetworkTableEvent.Kind> eventKinds) { 045 return NetworkTablesJNI.addListener(m_handle, topic.getHandle(), eventKinds); 046 } 047 048 /** 049 * Start listening to topic changes on a subscriber. This does NOT keep the subscriber active. 050 * 051 * @param subscriber Subscriber 052 * @param eventKinds set of event kinds to listen to 053 * @return Listener handle 054 */ 055 public int addListener(Subscriber subscriber, EnumSet<NetworkTableEvent.Kind> eventKinds) { 056 return NetworkTablesJNI.addListener(m_handle, subscriber.getHandle(), eventKinds); 057 } 058 059 /** 060 * Start listening to topic changes on a subscriber. This does NOT keep the subscriber active. 061 * 062 * @param subscriber Subscriber 063 * @param eventKinds set of event kinds to listen to 064 * @return Listener handle 065 */ 066 public int addListener(MultiSubscriber subscriber, EnumSet<NetworkTableEvent.Kind> eventKinds) { 067 return NetworkTablesJNI.addListener(m_handle, subscriber.getHandle(), eventKinds); 068 } 069 070 /** 071 * Start listening to topic changes on an entry. 072 * 073 * @param entry Entry 074 * @param eventKinds set of event kinds to listen to 075 * @return Listener handle 076 */ 077 public int addListener(NetworkTableEntry entry, EnumSet<NetworkTableEvent.Kind> eventKinds) { 078 return NetworkTablesJNI.addListener(m_handle, entry.getHandle(), eventKinds); 079 } 080 081 /** 082 * Add a connection listener. The callback function is called asynchronously on a separate thread, 083 * so it's important to use synchronization or atomics when accessing any shared state from the 084 * callback function. 085 * 086 * @param immediateNotify notify listener of all existing connections 087 * @return Listener handle 088 */ 089 public int addConnectionListener(boolean immediateNotify) { 090 EnumSet<NetworkTableEvent.Kind> eventKinds = EnumSet.of(NetworkTableEvent.Kind.kConnection); 091 if (immediateNotify) { 092 eventKinds.add(NetworkTableEvent.Kind.kImmediate); 093 } 094 return NetworkTablesJNI.addListener(m_handle, m_inst.getHandle(), eventKinds); 095 } 096 097 /** 098 * Add a time synchronization listener. The callback function is called asynchronously on a 099 * separate thread, so it's important to use synchronization or atomics when accessing any shared 100 * state from the callback function. 101 * 102 * @param immediateNotify notify listener of current time synchronization value 103 * @return Listener handle 104 */ 105 public int addTimeSyncListener(boolean immediateNotify) { 106 EnumSet<NetworkTableEvent.Kind> eventKinds = EnumSet.of(NetworkTableEvent.Kind.kTimeSync); 107 if (immediateNotify) { 108 eventKinds.add(NetworkTableEvent.Kind.kImmediate); 109 } 110 return NetworkTablesJNI.addListener(m_handle, m_inst.getHandle(), eventKinds); 111 } 112 113 /** 114 * Add logger callback function. By default, log messages are sent to stderr; this function sends 115 * log messages with the specified levels to the provided callback function instead. The callback 116 * function will only be called for log messages with level greater than or equal to minLevel and 117 * less than or equal to maxLevel; messages outside this range will be silently ignored. 118 * 119 * @param minLevel minimum log level 120 * @param maxLevel maximum log level 121 * @return Listener handle 122 */ 123 public int addLogger(int minLevel, int maxLevel) { 124 return NetworkTablesJNI.addLogger(m_handle, minLevel, maxLevel); 125 } 126 127 /** 128 * Remove a listener. 129 * 130 * @param listener Listener handle 131 */ 132 public void removeListener(int listener) { 133 NetworkTablesJNI.removeListener(listener); 134 } 135 136 /** 137 * Read topic notifications. 138 * 139 * @return Topic notifications since the previous call to readQueue() 140 */ 141 public NetworkTableEvent[] readQueue() { 142 return NetworkTablesJNI.readListenerQueue(m_inst, m_handle); 143 } 144 145 @Override 146 public synchronized void close() { 147 if (m_handle != 0) { 148 NetworkTablesJNI.destroyListenerPoller(m_handle); 149 } 150 m_handle = 0; 151 } 152 153 /** 154 * Determines if the native handle is valid. 155 * 156 * @return True if the native handle is valid, false otherwise. 157 */ 158 public boolean isValid() { 159 return m_handle != 0; 160 } 161 162 /** 163 * Gets the native handle. 164 * 165 * @return Handle 166 */ 167 public int getHandle() { 168 return m_handle; 169 } 170 171 private final NetworkTableInstance m_inst; 172 private int m_handle; 173}