com.chibchasoft.vertx.util.VertxUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.chibchasoft.vertx.util.VertxUtil.java

Source

/*
 * Copyright (c) 2017 chibchasoft.com
 * ------------------------------------------------------
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Apache License v2.0 which accompanies
 * this distribution.
 *
 *      The Apache License v2.0 is available at
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Author <a href="mailto:jvelez@chibchasoft.com">Juan Velez</a>
 */
package com.chibchasoft.vertx.util;

import com.chibchasoft.vertx.util.concurrent.ConcurrentReferenceHashMap;
import io.vertx.core.AsyncResult;
import io.vertx.core.Context;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.impl.ContextInternal;
import io.vertx.core.impl.TaskQueue;

/**
 * Collection of Vertx Utility methods.
 *
 * @author <a href="mailto:jvelez@chibchasoft.com">Juan Velez</a>
 */
public interface VertxUtil {
    /**
     * {@link Context}s are mapped to a Map of {@link Object}s to {@link TaskQueue}s
     */
    ConcurrentReferenceHashMap<Context, ConcurrentReferenceHashMap<Object, TaskQueue>> TASK_QUEUES = new ConcurrentReferenceHashMap<>(
            16, ConcurrentReferenceHashMap.ReferenceType.WEAK);

    /**
     * <p>Similar to {@link Context#executeBlocking(Handler, Handler)} but when this method is called several times on
     * the same {@link Context} for the same {@code identifier}, executions associated to that value for that context
     * will be executed serially. However, there will be no ordering guarantees in relation to executions for different
     * identifiers for the same context or even for the same identifier but for different contexts.</p>
     *
     * <p><b>NOTES:</b></p>
     *
     * - This method needs to be called within the scope of a Vertx Context.<br>
     * - This method relies on a Vertx internal API method
     * {@link ContextInternal#executeBlocking(Handler, TaskQueue, Handler)}.<br>
     *
     * @param identifier          Object used to group and serialize executions
     * @param blockingCodeHandler handler representing the blocking code to run
     * @param resultHandler       handler that will be called when the blocking code is complete
     * @param <T>                 the type of the result
     */
    static <T> void executeBlocking(Object identifier, Handler<Future<T>> blockingCodeHandler,
            Handler<AsyncResult<T>> resultHandler) {
        executeBlocking(Vertx.currentContext(), identifier, blockingCodeHandler, resultHandler);
    }

    /**
     * <p>Similar to {@link Context#executeBlocking(Handler, Handler)} but when this method is called several times on
     * the same provided {@code Context} for the same {@code identifier}, executions associated to that value for that
     * {@code context} will be executed serially. However, there will be no ordering guarantees in relation to
     * executions for different identifiers for the same {@code context} or even for the same identifier but for
     * different {@code context}s.</p>
     *
     * <p><b>NOTE:</b> This method relies on a Vertx internal API method
     * {@link ContextInternal#executeBlocking(Handler, TaskQueue, Handler)}</p>
     *
     * @param context             The {@link Context} to be used to execute the blocking code
     * @param identifier          Object used to group and serialize executions
     * @param blockingCodeHandler handler representing the blocking code to run
     * @param resultHandler       handler that will be called when the blocking code is complete
     * @param <T>                 the type of the result
     */
    static <T> void executeBlocking(Context context, Object identifier, Handler<Future<T>> blockingCodeHandler,
            Handler<AsyncResult<T>> resultHandler) {
        if (context == null)
            throw new IllegalStateException("A context is required");
        if (identifier == null)
            throw new IllegalArgumentException("An identifier is required");
        ContextInternal contextInternal = (ContextInternal) context;

        TaskQueue taskQueue = TASK_QUEUES
                .computeIfAbsent(context,
                        k -> new ConcurrentReferenceHashMap<>(16, ConcurrentReferenceHashMap.ReferenceType.WEAK))
                .computeIfAbsent(identifier, k -> new TaskQueue());

        contextInternal.executeBlocking(blockingCodeHandler, taskQueue, resultHandler);
    }
}