Skip to content

Commit

Permalink
[ntcore] Change Java event mask to EnumSet (wpilibsuite#4564)
Browse files Browse the repository at this point in the history
Also convert NetworkTableInstance.getNetworkMode() to return EnumSet.
  • Loading branch information
PeterJohnson authored Nov 5, 2022
1 parent fa44a07 commit 5005e2c
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 115 deletions.
109 changes: 75 additions & 34 deletions ntcore/src/generate/java/NetworkTableInstance.java.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package edu.wpi.first.networktables;
import edu.wpi.first.util.WPIUtilJNI;
import edu.wpi.first.util.concurrent.Event;
import edu.wpi.first.util.datalog.DataLog;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -35,16 +36,33 @@ import java.util.function.Consumer;
*/
@SuppressWarnings("PMD.CouplingBetweenObjects")
public final class NetworkTableInstance implements AutoCloseable {
/**
* Client/server mode flag values (as returned by {@link #getNetworkMode()}). This is a bitmask.
*/
public static final int kNetModeNone = 0x00;
/** Client/server mode flag values (as returned by {@link #getNetworkMode()}). */
public enum NetworkMode {
/** Running in server mode. */
kServer(0x01),

/** Running in NT3 client mode. */
kClient3(0x02),

/** Running in NT4 client mode. */
kClient4(0x04),

/** Currently starting up (either client or server). */
kStarting(0x08),

/** Running in local-only mode. */
kLocal(0x10);

private final int value;

NetworkMode(int value) {
this.value = value;
}

public static final int kNetModeServer = 0x01;
public static final int kNetModeClient3 = 0x02;
public static final int kNetModeClient4 = 0x04;
public static final int kNetModeStarting = 0x08;
public static final int kNetModeLocal = 0x10;
public int getValue() {
return value;
}
}

/** The default port that network tables operates on for NT3. */
public static final int kDefaultPort3 = 1735;
Expand Down Expand Up @@ -370,29 +388,35 @@ public final class NetworkTableInstance implements AutoCloseable {
m_inst = inst;
}

int add(String[] prefixes, int mask, Consumer<NetworkTableEvent> listener) {
int add(
String[] prefixes,
EnumSet<NetworkTableEvent.Kind> eventKinds,
Consumer<NetworkTableEvent> listener) {
m_lock.lock();
try {
if (m_poller == 0) {
m_poller = NetworkTablesJNI.createListenerPoller(m_inst.getHandle());
startThread();
}
int h = NetworkTablesJNI.addListener(m_poller, prefixes, mask);
int h = NetworkTablesJNI.addListener(m_poller, prefixes, eventKinds);
m_listeners.put(h, listener);
return h;
} finally {
m_lock.unlock();
}
}

int add(int handle, int mask, Consumer<NetworkTableEvent> listener) {
int add(
int handle,
EnumSet<NetworkTableEvent.Kind> eventKinds,
Consumer<NetworkTableEvent> listener) {
m_lock.lock();
try {
if (m_poller == 0) {
m_poller = NetworkTablesJNI.createListenerPoller(m_inst.getHandle());
startThread();
}
int h = NetworkTablesJNI.addListener(m_poller, handle, mask);
int h = NetworkTablesJNI.addListener(m_poller, handle, eventKinds);
m_listeners.put(h, listener);
return h;
} finally {
Expand Down Expand Up @@ -563,9 +587,11 @@ public final class NetworkTableInstance implements AutoCloseable {
*/
public int addConnectionListener(
boolean immediateNotify, Consumer<NetworkTableEvent> listener) {
return m_listeners.add(m_handle,
NetworkTableEvent.kConnection | (immediateNotify ? NetworkTableEvent.kImmediate : 0),
listener);
EnumSet<NetworkTableEvent.Kind> eventKinds = EnumSet.of(NetworkTableEvent.Kind.kConnection);
if (immediateNotify) {
eventKinds.add(NetworkTableEvent.Kind.kImmediate);
}
return m_listeners.add(m_handle, eventKinds, listener);
}

/**
Expand All @@ -577,16 +603,18 @@ public final class NetworkTableInstance implements AutoCloseable {
* listener.
*
* @param topic Topic
* @param eventMask Bitmask of TopicListenerFlags values
* @param eventKinds set of event kinds to listen to
* @param listener Listener function
* @return Listener handle
*/
public int addListener(
Topic topic, int eventMask, Consumer<NetworkTableEvent> listener) {
Topic topic,
EnumSet<NetworkTableEvent.Kind> eventKinds,
Consumer<NetworkTableEvent> listener) {
if (topic.getInstance().getHandle() != m_handle) {
throw new IllegalArgumentException("topic is not from this instance");
}
return m_listeners.add(topic.getHandle(), eventMask, listener);
return m_listeners.add(topic.getHandle(), eventKinds, listener);
}

/**
Expand All @@ -596,16 +624,18 @@ public final class NetworkTableInstance implements AutoCloseable {
* active.
*
* @param subscriber Subscriber
* @param eventMask Bitmask of TopicListenerFlags values
* @param eventKinds set of event kinds to listen to
* @param listener Listener function
* @return Listener handle
*/
public int addListener(
Subscriber subscriber, int eventMask, Consumer<NetworkTableEvent> listener) {
Subscriber subscriber,
EnumSet<NetworkTableEvent.Kind> eventKinds,
Consumer<NetworkTableEvent> listener) {
if (subscriber.getTopic().getInstance().getHandle() != m_handle) {
throw new IllegalArgumentException("subscriber is not from this instance");
}
return m_listeners.add(subscriber.getHandle(), eventMask, listener);
return m_listeners.add(subscriber.getHandle(), eventKinds, listener);
}

/**
Expand All @@ -615,16 +645,18 @@ public final class NetworkTableInstance implements AutoCloseable {
* active.
*
* @param subscriber Subscriber
* @param eventMask Bitmask of TopicListenerFlags values
* @param eventKinds set of event kinds to listen to
* @param listener Listener function
* @return Listener handle
*/
public int addListener(
MultiSubscriber subscriber, int eventMask, Consumer<NetworkTableEvent> listener) {
MultiSubscriber subscriber,
EnumSet<NetworkTableEvent.Kind> eventKinds,
Consumer<NetworkTableEvent> listener) {
if (subscriber.getInstance().getHandle() != m_handle) {
throw new IllegalArgumentException("subscriber is not from this instance");
}
return m_listeners.add(subscriber.getHandle(), eventMask, listener);
return m_listeners.add(subscriber.getHandle(), eventKinds, listener);
}

/**
Expand All @@ -633,16 +665,18 @@ public final class NetworkTableInstance implements AutoCloseable {
* accessing any shared state from the callback function.
*
* @param entry Entry
* @param eventMask Bitmask of TopicListenerFlags values
* @param eventKinds set of event kinds to listen to
* @param listener Listener function
* @return Listener handle
*/
public int addListener(
NetworkTableEntry entry, int eventMask, Consumer<NetworkTableEvent> listener) {
NetworkTableEntry entry,
EnumSet<NetworkTableEvent.Kind> eventKinds,
Consumer<NetworkTableEvent> listener) {
if (entry.getTopic().getInstance().getHandle() != m_handle) {
throw new IllegalArgumentException("entry is not from this instance");
}
return m_listeners.add(entry.getHandle(), eventMask, listener);
return m_listeners.add(entry.getHandle(), eventKinds, listener);
}

/**
Expand All @@ -655,15 +689,15 @@ public final class NetworkTableInstance implements AutoCloseable {
* listener.
*
* @param prefixes Topic name string prefixes
* @param eventMask Bitmask of TopicListenerFlags values
* @param eventKinds set of event kinds to listen to
* @param listener Listener function
* @return Listener handle
*/
public int addListener(
String[] prefixes,
int eventMask,
EnumSet<NetworkTableEvent.Kind> eventKinds,
Consumer<NetworkTableEvent> listener) {
return m_listeners.add(prefixes, eventMask, listener);
return m_listeners.add(prefixes, eventKinds, listener);
}

/*
Expand All @@ -673,10 +707,17 @@ public final class NetworkTableInstance implements AutoCloseable {
/**
* Get the current network mode.
*
* @return Bitmask of NetworkMode.
* @return Enum set of NetworkMode.
*/
public int getNetworkMode() {
return NetworkTablesJNI.getNetworkMode(m_handle);
public EnumSet<NetworkMode> getNetworkMode() {
int flags = NetworkTablesJNI.getNetworkMode(m_handle);
EnumSet<NetworkMode> rv = EnumSet.noneOf(NetworkMode.class);
for (NetworkMode mode : NetworkMode.values()) {
if ((flags & mode.getValue()) != 0) {
rv.add(mode);
}
}
return rv;
}

/**
Expand Down
17 changes: 17 additions & 0 deletions ntcore/src/generate/java/NetworkTablesJNI.java.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package edu.wpi.first.networktables;
import edu.wpi.first.util.RuntimeLoader;
import edu.wpi.first.util.datalog.DataLog;
import java.io.IOException;
import java.util.EnumSet;
import java.util.concurrent.atomic.AtomicBoolean;

public final class NetworkTablesJNI {
Expand Down Expand Up @@ -203,6 +204,22 @@ public final class NetworkTablesJNI {

public static native void destroyListenerPoller(int poller);

private static int kindsToMask(EnumSet<NetworkTableEvent.Kind> kinds) {
int mask = 0;
for (NetworkTableEvent.Kind kind : kinds) {
mask |= kind.getValue();
}
return mask;
}

public static int addListener(int poller, String[] prefixes, EnumSet<NetworkTableEvent.Kind> kinds) {
return addListener(poller, prefixes, kindsToMask(kinds));
}

public static int addListener(int poller, int handle, EnumSet<NetworkTableEvent.Kind> kinds) {
return addListener(poller, handle, kindsToMask(kinds));
}

public static native int addListener(int poller, String[] prefixes, int mask);

public static native int addListener(int poller, int handle, int mask);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,61 @@
/**
* NetworkTables event.
*
* <p>Events have flags. The flags are a bitmask and must be OR'ed together when listening to an
* event to indicate the combination of events desired to be received.
* <p>There are different kinds of events. When creating a listener, a combination of event kinds
* can be listened to by building an EnumSet of NetworkTableEvent.Kind.
*/
@SuppressWarnings("MemberName")
public final class NetworkTableEvent {
/** No flags. */
public static final int kNone = 0;
public enum Kind {
/**
* Initial listener addition. Set this to receive immediate notification of matches to other
* criteria.
*/
kImmediate(0x0001),

/**
* Initial listener addition. Set this flag to receive immediate notification of matches to the
* flag criteria.
*/
public static final int kImmediate = 0x01;
/** Client connected (on server, any client connected). */
kConnected(0x0002),

/** Client disconnected (on server, any client disconnected). */
kDisconnected(0x0004),

/** Any connection event (connect or disconnect). */
kConnection(0x0004 | 0x0002),

/** Client connected (on server, any client connected). */
public static final int kConnected = 0x02;
/** New topic published. */
kPublish(0x0008),

/** Client disconnected (on server, any client disconnected). */
public static final int kDisconnected = 0x04;
/** Topic unpublished. */
kUnpublish(0x0010),

/** Any connection event (connect or disconnect). */
public static final int kConnection = kConnected | kDisconnected;
/** Topic properties changed. */
kProperties(0x0020),

/** New topic published. */
public static final int kPublish = 0x08;
/** Any topic event (publish, unpublish, or properties changed). */
kTopic(0x0020 | 0x0010 | 0x0008),

/** Topic unpublished. */
public static final int kUnpublish = 0x10;
/** Topic value updated (via network). */
kValueRemote(0x0040),

/** Topic properties changed. */
public static final int kProperties = 0x20;
/** Topic value updated (local). */
kValueLocal(0x0080),

/** Any topic event (publish, unpublish, or properties changed). */
public static final int kTopic = kPublish | kUnpublish | kProperties;
/** Topic value updated (network or local). */
kValueAll(0x0080 | 0x0040),

/** Topic value updated (via network). */
public static final int kValueRemote = 0x40;
/** Log message. */
kLogMessage(0x0100);

/** Topic value updated (local). */
public static final int kValueLocal = 0x80;
private final int value;

/** Topic value updated (network or local). */
public static final int kValueAll = kValueRemote | kValueLocal;
Kind(int value) {
this.value = value;
}

/** Log message. */
public static final int kLogMessage = 0x100;
public int getValue() {
return value;
}
}

/**
* Handle of listener that was triggered. The value returned when adding the listener can be used
Expand All @@ -61,17 +70,24 @@ public final class NetworkTableEvent {
public final int listener;

/**
* Event flags. For example, kPublish if the topic was not previously published. Also indicates
* the data included with the event:
* Determine if event is of a particular kind. For example, kPublish if the topic was not
* previously published. Also indicates the data included with the event:
*
* <ul>
* <li>kConnected or kDisconnected: connInfo
* <li>kPublish, kUnpublish, or kProperties: topicInfo
* <li>kValueRemote, kValueLocal: valueData
* <li>kLogMessage: logMessage
* </ul>
*
* @param kind Kind
* @return True if event matches kind
*/
public final int flags;
public boolean is(Kind kind) {
return (m_flags & kind.getValue()) != 0;
}

private final int m_flags;

/** Connection information (for connection events). */
public final ConnectionInfo connInfo;
Expand Down Expand Up @@ -106,7 +122,7 @@ public NetworkTableEvent(
LogMessage logMessage) {
this.m_inst = inst;
this.listener = listener;
this.flags = flags;
this.m_flags = flags;
this.connInfo = connInfo;
this.topicInfo = topicInfo;
this.valueData = valueData;
Expand Down
Loading

0 comments on commit 5005e2c

Please sign in to comment.