CC-Tweaked/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/ModemState.java

99 lines
2.7 KiB
Java

// SPDX-FileCopyrightText: 2018 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.peripheral.modem;
import dan200.computercraft.api.lua.LuaException;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import javax.annotation.Nullable;
import java.util.concurrent.atomic.AtomicBoolean;
public final class ModemState {
private final @Nullable Runnable onChanged;
private final AtomicBoolean changed = new AtomicBoolean(true);
private boolean open = false;
private final IntSet channels = new IntOpenHashSet();
public ModemState() {
onChanged = null;
}
public ModemState(Runnable onChanged) {
this.onChanged = onChanged;
}
private void setOpen(boolean open) {
if (this.open == open) return;
this.open = open;
if (!changed.getAndSet(true) && onChanged != null) onChanged.run();
}
public boolean pollChanged() {
return changed.getAndSet(false);
}
public boolean isOpen() {
return open;
}
public boolean isOpen(int channel) {
synchronized (channels) {
return channels.contains(channel);
}
}
public void open(int channel) throws LuaException {
synchronized (channels) {
if (!channels.contains(channel)) {
if (channels.size() >= 128) throw new LuaException("Too many open channels");
channels.add(channel);
setOpen(true);
}
}
}
public void close(int channel) {
synchronized (channels) {
channels.remove(channel);
if (channels.isEmpty()) setOpen(false);
}
}
public void closeAll() {
synchronized (channels) {
channels.clear();
setOpen(false);
}
}
/**
* Copy this modem state, returning a new instance. The new instance will have the same set of open channels but no
* on-change listener.
*
* @return The new modem state.
*/
public ModemState copy() {
return copy(null);
}
/**
* Copy this modem state, returning a new instance. The new instance will have the same set of open channels and a
* different on-change listener.
*
* @param onChanged The on-change listener.
* @return The new modem state.
*/
public ModemState copy(@Nullable Runnable onChanged) {
synchronized (channels) {
var clone = onChanged == null ? new ModemState() : new ModemState(onChanged);
clone.channels.addAll(channels);
clone.open = open;
return clone;
}
}
}