
io.jsync.net.impl.AsyncEventLoopGroup Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jsync.io Show documentation
Show all versions of jsync.io Show documentation
jsync.io is a non-blocking, event-driven networking framework for Java
/*
* Copyright (c) 2011-2013 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.jsync.net.impl;
import io.netty.channel.*;
import io.netty.util.concurrent.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Tim Fox
*/
@SuppressWarnings("deprecation")
public final class AsyncEventLoopGroup extends AbstractEventExecutorGroup implements EventLoopGroup {
private final List workers = new ArrayList<>();
private final CountDownLatch latch = new CountDownLatch(1);
private final AtomicBoolean gracefulShutdown = new AtomicBoolean();
private final Promise> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
private int pos;
@Override
public synchronized EventLoop next() {
if (workers.isEmpty()) {
throw new IllegalStateException();
} else {
EventLoop worker = workers.get(pos).worker;
pos++;
checkPos();
return worker;
}
}
@Override
public Iterator iterator() {
return new EventLoopIterator(workers.iterator());
}
@Override
public ChannelFuture register(Channel channel) {
return next().register(channel);
}
@Override
public ChannelFuture register(Channel channel, ChannelPromise promise) {
return next().register(channel, promise);
}
@Override
public boolean isShutdown() {
return latch.getCount() == 0;
}
@Override
public boolean isTerminated() {
return isShutdown();
}
@Override
public synchronized boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return latch.await(timeout, unit);
}
public synchronized void addWorker(EventLoop worker) {
EventLoopHolder holder = findHolder(worker);
if (holder == null) {
workers.add(new EventLoopHolder(worker));
} else {
holder.count++;
}
}
public synchronized void shutdown() {
for (EventLoopHolder holder : workers) {
holder.worker.shutdown();
}
latch.countDown();
}
@Override
public boolean isShuttingDown() {
return gracefulShutdown.get();
}
@Override
public Future> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
if (gracefulShutdown.compareAndSet(false, true)) {
final AtomicInteger counter = new AtomicInteger(workers.size());
for (EventLoopHolder holder : workers) {
holder.worker.shutdownGracefully().addListener(new GenericFutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (counter.decrementAndGet() == 0) {
terminationFuture.setSuccess(null);
}
}
});
}
}
return terminationFuture;
}
@Override
public Future> terminationFuture() {
return terminationFuture;
}
private EventLoopHolder findHolder(EventLoop worker) {
EventLoopHolder wh = new EventLoopHolder(worker);
for (EventLoopHolder holder : workers) {
if (holder.equals(wh)) {
return holder;
}
}
return null;
}
public synchronized void removeWorker(EventLoop worker) {
//TODO can be optimised
EventLoopHolder holder = findHolder(worker);
if (holder != null) {
holder.count--;
if (holder.count == 0) {
workers.remove(holder);
}
checkPos();
} else {
throw new IllegalStateException("Can't find worker to remove");
}
}
public synchronized int workerCount() {
return workers.size();
}
private void checkPos() {
if (pos == workers.size()) {
pos = 0;
}
}
private static class EventLoopHolder {
final EventLoop worker;
int count = 1;
EventLoopHolder(EventLoop worker) {
this.worker = worker;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EventLoopHolder that = (EventLoopHolder) o;
if (worker != null ? !worker.equals(that.worker) : that.worker != null) return false;
return true;
}
@Override
public int hashCode() {
return worker != null ? worker.hashCode() : 0;
}
}
private static final class EventLoopIterator implements Iterator {
private final Iterator holderIt;
public EventLoopIterator(Iterator holderIt) {
this.holderIt = holderIt;
}
@Override
public boolean hasNext() {
return holderIt.hasNext();
}
@Override
public EventExecutor next() {
return holderIt.next().worker;
}
@Override
public void remove() {
throw new UnsupportedOperationException("read-only");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy