99 lines
2.7 KiB
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;
|
|
}
|
|
}
|
|
}
|