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

software.amazon.awssdk.http.nio.netty.internal.SharedSdkEventLoopGroup Maven / Gradle / Ivy

Go to download

A single bundled dependency that includes all service and dependent JARs with third-party libraries relocated to different namespaces.

There is a newer version: 2.5.20
Show newest version
/*
 * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.http.nio.netty.internal;

import io.netty.channel.EventLoopGroup;
import io.netty.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.annotations.SdkTestInternalApi;
import software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup;

/**
 * Provides access and manages a shared {@link SdkEventLoopGroup}. Uses reference counting to keep track of how many HTTP
 * clients are using the shared event loop group and will automatically close it when that count reaches zero. Event loop
 * group is lazily initialized for the first time and and subsequent requests after the count reaches zero.
 */
@SdkInternalApi
public final class SharedSdkEventLoopGroup {

    /**
     * Lazily initialized shared default event loop group.
     */
    private static SdkEventLoopGroup sharedSdkEventLoopGroup;

    /**
     * Reference count of clients using the shared event loop group.
     */
    private static int referenceCount = 0;

    private SharedSdkEventLoopGroup() {
    }

    /**
     * @return The default {@link SdkEventLoopGroup} that will be shared across all service clients.
     * This is used when the customer does not specify a custom {@link SdkEventLoopGroup} or {@link SdkEventLoopGroup.Builder}.
     */
    @SdkInternalApi
    public static synchronized SdkEventLoopGroup get() {
        if (sharedSdkEventLoopGroup == null) {
            sharedSdkEventLoopGroup = SdkEventLoopGroup.builder().build();
        }
        referenceCount++;
        return SdkEventLoopGroup.create(new ReferenceCountingEventLoopGroup(sharedSdkEventLoopGroup.eventLoopGroup()),
                                        sharedSdkEventLoopGroup.channelFactory());
    }

    /**
     * Decrement the reference count and close if necessary.
     */
    private static synchronized void decrementReference() {
        referenceCount--;
        if (referenceCount == 0) {
            sharedSdkEventLoopGroup.eventLoopGroup().shutdownGracefully();
            sharedSdkEventLoopGroup = null;
        }
    }

    @SdkTestInternalApi
    static synchronized int referenceCount() {
        return referenceCount;
    }

    /**
     * Special event loop group that prevents shutdown and decrements the reference count when the event loop group
     * is closed.
     */
    private static class ReferenceCountingEventLoopGroup extends DelegatingEventLoopGroup {

        private final AtomicBoolean hasBeenClosed = new AtomicBoolean(false);

        private ReferenceCountingEventLoopGroup(EventLoopGroup delegate) {
            super(delegate);
        }

        @Override
        public Future shutdownGracefully() {
            // Only want to decrement the reference the first time it's closed. Shutdown is idempotent and may be
            // called multiple times.
            if (hasBeenClosed.compareAndSet(false, true)) {
                decrementReference();
            }
            return null;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy