package org.scribble.net.session;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.scribble.main.RuntimeScribbleException;
import org.scribble.net.ScribInterrupt;
import org.scribble.net.ScribMessage;
import org.scribble.sesstype.name.Role;
@Deprecated
public class EndpointInputQueues
{
// FIXME: factor out individual role queues (with counts and tickets, and bounded cache size?)
private final Map<Role, List<ScribMessage>> queues = new HashMap<>();
//private final List<Object> list = new LinkedList<>();
private final Map<Role, Integer> counts = new HashMap<>(); // How many ScribMessages read so far
private final Map<Role, Integer> tickets = new HashMap<>(); // Index of the next expected ScribMessage
public EndpointInputQueues()
{
}
public synchronized int getTicket(Role peer)
{
int next = this.tickets.get(peer) + 1;
this.tickets.put(peer, next);
return next;
}
public synchronized void register(Role peer)
{
this.queues.put(peer, new LinkedList<>());
this.counts.put(peer, 0);
this.tickets.put(peer, 0);
}
public synchronized void enqueue(Role peer, ScribMessage o)
{
this.queues.get(peer).add(o);
//this.list.add(o);
this.counts.put(peer, this.counts.get(peer) + 1);
notifyAll(); // FIXME: notify just for each peer
}
public synchronized void interrupt(Role peer, Throwable t)
{
enqueue(peer, new ScribInterrupt(t));
}
public synchronized boolean isEmpty(Role peer)
{
return this.queues.get(peer).isEmpty();
}
/*public synchronized Object peek(Role src)
{
return this.queues.get(src).get(0);
}*/
// Default CompletableFuture executed by common forkjoin pool -- so all messages that are received/async'd will eventually be pulled from the queue (no manual GC necessary)
public synchronized CompletableFuture<ScribMessage> getFuture(Role peer)
{
// FIXME: better exception handling (integrate with Future interface?)
return CompletableFuture.supplyAsync(() ->
{
try
{
ScribMessage m = dequeue(peer, getTicket(peer));
if (m instanceof ScribInterrupt) // FIXME: hacked in
{
throw new RuntimeScribbleException((Throwable) ((ScribInterrupt) m).payload[0]);
}
return m;
}
catch(IOException e)
{
throw new RuntimeScribbleException(e);
}
});
}
protected synchronized ScribMessage dequeue(Role peer, int ticket) throws IOException
{
try
{
while (this.counts.get(peer) < ticket)
{
wait();
}
List<ScribMessage> queue = this.queues.get(peer);
while (queue.isEmpty())
{
wait();
}
ScribMessage m = queue.remove(0);
//this.list.remove(o);
return m;
}
catch (InterruptedException e)
{
throw new IOException(e);
}
}
/*public boolean isEmpty()
{
return this.list.isEmpty();
}*/
/*public Object dequeue()
{
Object o = this.list.remove(0);
for (List<Object> os : this.global.values())
{
if (os.contains(o))
{
os.remove(o);
break;
}
}
return o;
}*/
/*// Synchronized against usage in SocketEndpoint
public synchronized Object readObject() throws IOException
{
synchronized (this)
{
while (isEmpty())
{
try
{
this.wait();
}
catch (InterruptedException e)
{
throw new IOException(e);
}
}
return dequeue();
}
}*/
/*public ScribbleInterrupt checkForInterrupt()
{
synchronized (this)
{
for (List<Object> queue : this.global.values())
{
if (!queue.isEmpty() && (queue.get(0) instanceof ScribbleInterrupt))
{
return (ScribbleInterrupt) queue.remove(0);
}
}
}
return null;
}*/
}