All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.wjybxx.concurrent.DefaultFixedEventLoopGroup Maven / Gradle / Ivy

/*
 * Copyright 2023-2024 wjybxx([email protected])
 *
 * Licensed 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 cn.wjybxx.concurrent;

import cn.wjybxx.base.function.TriConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

/**
 * @author wjybxx
 * date 2023/4/8
 */
public class DefaultFixedEventLoopGroup extends AbstractEventLoopGroup implements FixedEventLoopGroup {

    private static final Logger logger = LoggerFactory.getLogger(DefaultFixedEventLoopGroup.class);
    private final IPromise terminationFuture = new Promise<>();

    private final EventLoop[] children;
    private final List readonlyChildren;
    private final EventLoopChooser chooser;
    private final Runnable terminationHook;

    public DefaultFixedEventLoopGroup(EventLoopGroupBuilder builder) {
        int numChildren = builder.getNumChildren();
        if (numChildren < 1) {
            throw new IllegalArgumentException("childCount must greater than 0");
        }
        EventLoopFactory eventLoopFactory = builder.getEventLoopFactory();
        if (eventLoopFactory == null) {
            throw new NullPointerException("eventLoopFactory");
        }
        EventLoopChooserFactory chooserFactory = builder.getChooserFactory();
        if (chooserFactory == null) {
            chooserFactory = new DefaultChooserFactory();
        }

        children = new EventLoop[numChildren];
        for (int i = 0; i < numChildren; i++) {
            EventLoop eventLoop = Objects.requireNonNull(eventLoopFactory.newChild(this, i, null));
            if (eventLoop.parent() != this) throw new IllegalStateException("the parent of child is illegal");
            children[i] = eventLoop;
        }
        readonlyChildren = List.of(children);
        chooser = chooserFactory.newChooser(children.clone()); // 避免错误的实现修改引用
        terminationHook = builder.getTerminationHook();

        // 最后再监听,否则可能状态错误
        final ChildrenTerminateListener terminationListener = new ChildrenTerminateListener();
        for (EventLoop child : children) {
            child.terminationFuture().whenComplete(terminationListener);
        }
    }

    // -------------------------------------  子类生命周期管理 --------------------------------

    @Override
    public IFuture terminationFuture() {
        return terminationFuture.asReadonly();
    }

    @Override
    public boolean isShuttingDown() {
        return Arrays.stream(children).allMatch(EventLoop::isShuttingDown);
    }

    @Override
    public boolean isShutdown() {
        return Arrays.stream(children).allMatch(EventLoop::isShutdown);
    }

    @Override
    public boolean isTerminated() {
        return terminationFuture.isDone();
    }

    @Override
    public boolean awaitTermination(long timeout, @Nonnull TimeUnit unit) throws InterruptedException {
        return terminationFuture().await(timeout, unit);
    }

    @Override
    public void shutdown() {
        forEach(EventLoop::shutdown);
    }

    @Nonnull
    @Override
    public List shutdownNow() {
        List tasks = new ArrayList<>();
        for (EventLoop eventLoop : children) {
            tasks.addAll(eventLoop.shutdownNow());
        }
        return tasks;
    }

    /**
     * 当所有的子节点都进入终结状态时,该方法将被调用
     * 通常用于执行一些清理工作
     */
    protected void invokeTerminationHook() {
        if (terminationHook != null) {
            terminationHook.run();
        }
    }

    // ------------------------------------- 迭代 ----------------------------

    @Override
    public int childCount() {
        return children.length;
    }

    @Nonnull
    @Override
    public EventLoop select() {
        return chooser.select();
    }

    @Nonnull
    @Override
    public EventLoop select(int key) {
        return chooser.select(key);
    }

    @Nonnull
    @Override
    public Iterator iterator() {
        return readonlyChildren.iterator();
    }

    @Override
    public void forEach(Consumer action) {
        readonlyChildren.forEach(action);
    }

    @Override
    public Spliterator spliterator() {
        return readonlyChildren.spliterator();
    }
    //

    /** 子节点终结状态监听器 */
    private class ChildrenTerminateListener implements TriConsumer {

        /** 已关闭的子节点数量 */
        private final AtomicInteger terminatedChildren = new AtomicInteger(0);

        private ChildrenTerminateListener() {

        }

        @Override
        public void accept(IContext ctx, Object o, Throwable throwable) {
            if (terminatedChildren.incrementAndGet() == children.length) {
                try {
                    invokeTerminationHook();
                } catch (Throwable e) {
                    logger.error("terminateHook caught exception!", e);
                } finally {
                    terminationFuture.trySetResult(null);
                }
            }
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy