diff --git a/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java index 7b1cb9b711..bb1b054c21 100644 --- a/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java @@ -15,6 +15,8 @@ */ package io.netty.util.concurrent; +import java.util.Iterator; +import java.util.NoSuchElementException; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.Callable; import java.util.concurrent.RunnableFuture; @@ -30,6 +32,11 @@ public abstract class AbstractEventExecutor extends AbstractExecutorService impl return this; } + @Override + public Iterator iterator() { + return new EventExecutorIterator(); + } + @Override public Promise newPromise() { return new DefaultPromise(this); @@ -91,4 +98,26 @@ public abstract class AbstractEventExecutor extends AbstractExecutorService impl throw new UnsupportedOperationException(); } + private final class EventExecutorIterator implements Iterator { + private boolean nextCalled; + + @Override + public boolean hasNext() { + return !nextCalled; + } + + @Override + public EventExecutor next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + nextCalled = true; + return AbstractEventExecutor.this; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("read-only"); + } + } } diff --git a/common/src/main/java/io/netty/util/concurrent/EventExecutorGroup.java b/common/src/main/java/io/netty/util/concurrent/EventExecutorGroup.java index f465885130..74cc7f5f20 100644 --- a/common/src/main/java/io/netty/util/concurrent/EventExecutorGroup.java +++ b/common/src/main/java/io/netty/util/concurrent/EventExecutorGroup.java @@ -15,8 +15,8 @@ */ package io.netty.util.concurrent; +import java.util.Iterator; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -26,13 +26,20 @@ import java.util.concurrent.TimeUnit; * to shut them down in a global fashion. * */ -public interface EventExecutorGroup extends ScheduledExecutorService { +public interface EventExecutorGroup extends ScheduledExecutorService, Iterable { /** * Returns one of the {@link EventExecutor}s that belong to this group. */ EventExecutor next(); + /** + * Returns a read-only {@link Iterator} over all {@link EventExecutor}, which are handled by this + * {@link EventExecutorGroup} at the time of invoke this method. + */ + @Override + Iterator iterator(); + @Override Future submit(Runnable task); diff --git a/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java b/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java index ff31a1b8cb..5e802683df 100644 --- a/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java +++ b/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java @@ -16,6 +16,7 @@ package io.netty.util.concurrent; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Set; import java.util.concurrent.ThreadFactory; @@ -75,6 +76,19 @@ public abstract class MultithreadEventExecutorGroup extends AbstractEventExecuto return children[Math.abs(childIndex.getAndIncrement() % children.length)]; } + @Override + public Iterator iterator() { + return children().iterator(); + } + + /** + * Return the number of {@link EventExecutor} this implementation uses. This number is the maps + * 1:1 to the threads it use. + */ + public final int executorCount() { + return children.length; + } + /** * Return a safe-copy of all of the children of this group. */ diff --git a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java index 416204cc4c..f24063962d 100644 --- a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java @@ -260,6 +260,13 @@ public abstract class SingleThreadEventExecutor extends AbstractEventExecutor { return !taskQueue.isEmpty(); } + /** + * Return the number of tasks that are pending for processing. + */ + public final int pendingTasks() { + return taskQueue.size(); + } + /** * Add a task to the task queue, or throws a {@link RejectedExecutionException} if this instance was shutdown * before. diff --git a/common/src/main/java/io/netty/util/internal/ReadOnlyIterator.java b/common/src/main/java/io/netty/util/internal/ReadOnlyIterator.java new file mode 100644 index 0000000000..f4843e5ff8 --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/ReadOnlyIterator.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.netty.util.internal; + +import java.util.Iterator; + +public final class ReadOnlyIterator implements Iterator { + private final Iterator iterator; + + public ReadOnlyIterator(Iterator iterator) { + if (iterator == null) { + throw new NullPointerException("iterator"); + } + this.iterator = iterator; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + return iterator.next(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("read-only"); + } +} diff --git a/transport/src/main/java/io/netty/channel/EventLoopGroup.java b/transport/src/main/java/io/netty/channel/EventLoopGroup.java index d8c86f9c48..ab2f362408 100644 --- a/transport/src/main/java/io/netty/channel/EventLoopGroup.java +++ b/transport/src/main/java/io/netty/channel/EventLoopGroup.java @@ -18,7 +18,7 @@ package io.netty.channel; import io.netty.util.concurrent.EventExecutorGroup; /** - * Special {@link io.netty.util.concurrent.EventExecutorGroup} which allows to register {@link Channel}'s that get + * Special {@link EventExecutorGroup} which allows to register {@link Channel}'s that get * processed for later selection during the event loop. * */ diff --git a/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java b/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java index e9ec3b6983..8ffa789ba5 100644 --- a/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java +++ b/transport/src/main/java/io/netty/channel/ThreadPerChannelEventLoopGroup.java @@ -17,9 +17,12 @@ package io.netty.channel; import io.netty.util.concurrent.AbstractEventExecutorGroup; +import io.netty.util.concurrent.EventExecutor; import io.netty.util.internal.PlatformDependent; +import io.netty.util.internal.ReadOnlyIterator; import java.util.Collections; +import java.util.Iterator; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; @@ -105,6 +108,11 @@ public class ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup i return new ThreadPerChannelEventLoop(this); } + @Override + public Iterator iterator() { + return new ReadOnlyIterator(activeChildren.iterator()); + } + @Override public EventLoop next() { throw new UnsupportedOperationException();