io.vertx.core.Context Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.core;
import io.vertx.codegen.annotations.Fluent;
import io.vertx.codegen.annotations.GenIgnore;
import io.vertx.codegen.annotations.Nullable;
import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.impl.VertxThread;
import io.vertx.core.impl.launcher.VertxCommandLauncher;
import io.vertx.core.json.JsonObject;
import java.util.List;
import java.util.concurrent.Callable;
/**
* The execution context of a {@link io.vertx.core.Handler} execution.
*
* When Vert.x provides an event to a handler or calls the start or stop methods of a {@link io.vertx.core.Verticle},
* the execution is associated with a {@code Context}.
*
* Usually a context is an *event-loop context* and is tied to a specific event loop thread. So executions for that
* context always occur on that exact same event loop thread.
*
* In the case of worker verticles and running inline blocking code a worker context will be associated with the execution
* which will use a thread from the worker thread pool.
*
* When a handler is set by a thread associated with a specific context, the Vert.x will guarantee that when that handler
* is executed, that execution will be associated with the same context.
*
* If a handler is set by a thread not associated with a context (i.e. a non Vert.x thread). Then a new context will
* be created for that handler.
*
* In other words, a context is propagated.
*
* This means that when a verticle is deployed, any handlers it sets will be associated with the same context - the context
* of the verticle.
*
* This means (in the case of a standard verticle) that the verticle code will always be executed with the exact same
* thread, so you don't have to worry about multi-threaded acccess to the verticle state and you can code your application
* as single threaded.
*
* This class also allows arbitrary data to be {@link #put} and {@link #get} on the context so it can be shared easily
* amongst different handlers of, for example, a verticle instance.
*
* This class also provides {@link #runOnContext} which allows an action to be executed asynchronously using the same context.
*
* @author Tim Fox
*/
@VertxGen
public interface Context {
/**
* Is the current thread a worker thread?
*
* NOTE! This is not always the same as calling {@link Context#isWorkerContext}. If you are running blocking code
* from an event loop context, then this will return true but {@link Context#isWorkerContext} will return false.
*
* @return true if current thread is a worker thread, false otherwise
*/
static boolean isOnWorkerThread() {
Thread t = Thread.currentThread();
return t instanceof VertxThread && ((VertxThread) t).isWorker();
}
/**
* Is the current thread an event thread?
*
* NOTE! This is not always the same as calling {@link Context#isEventLoopContext}. If you are running blocking code
* from an event loop context, then this will return false but {@link Context#isEventLoopContext} will return true.
*
* @return true if current thread is an event thread, false otherwise
*/
static boolean isOnEventLoopThread() {
Thread t = Thread.currentThread();
return t instanceof VertxThread && !((VertxThread) t).isWorker();
}
/**
* Is the current thread a Vert.x thread? That's either a worker thread or an event loop thread
*
* @return true if current thread is a Vert.x thread, false otherwise
*/
static boolean isOnVertxThread() {
return Thread.currentThread() instanceof VertxThread;
}
/**
* Run the specified action asynchronously on the same context, some time after the current execution has completed.
*
* @param action the action to run
*/
void runOnContext(Handler action);
/**
* Safely execute some blocking code.
*
* Executes the blocking code in the handler {@code blockingCodeHandler} using a thread from the worker pool.
*
* The returned future will be completed with the result on the original context (i.e. on the original event loop of the caller)
* or failed when the handler throws an exception.
*
* A {@code Future} instance is passed into {@code blockingCodeHandler}. When the blocking code successfully completes,
* the handler should call the {@link Promise#complete} or {@link Promise#complete(Object)} method, or the {@link Promise#fail}
* method if it failed.
*
* The blocking code should block for a reasonable amount of time (i.e no more than a few seconds). Long blocking operations
* or polling operations (i.e a thread that spin in a loop polling events in a blocking fashion) are precluded.
*
* When the blocking operation lasts more than the 10 seconds, a message will be printed on the console by the
* blocked thread checker.
*
* Long blocking operations should use a dedicated thread managed by the application, which can interact with
* verticles using the event-bus or {@link Context#runOnContext(Handler)}
*
* @param blockingCodeHandler handler representing the blocking code to run
* @param resultHandler handler that will be called when the blocking code is complete
* @param ordered if true then if executeBlocking is called several times on the same context, the executions
* for that context will be executed serially, not in parallel. if false then they will be no ordering
* guarantees
* @param the type of the result
* @deprecated instead use {@link #executeBlocking(Callable, boolean)}
*/
@Deprecated
void executeBlocking(Handler> blockingCodeHandler, boolean ordered, Handler> resultHandler);
/**
* Safely execute some blocking code.
*
* Executes the blocking code in the handler {@code blockingCodeHandler} using a thread from the worker pool.
*
* The returned future will be completed with the result on the original context (i.e. on the original event loop of the caller)
* or failed when the handler throws an exception.
*
* The blocking code should block for a reasonable amount of time (i.e no more than a few seconds). Long blocking operations
* or polling operations (i.e a thread that spin in a loop polling events in a blocking fashion) are precluded.
*
* When the blocking operation lasts more than the 10 seconds, a message will be printed on the console by the
* blocked thread checker.
*
* Long blocking operations should use a dedicated thread managed by the application, which can interact with
* verticles using the event-bus or {@link Context#runOnContext(Handler)}
*
* @param blockingCodeHandler handler representing the blocking code to run
* @param ordered if true then if executeBlocking is called several times on the same context, the executions
* for that context will be executed serially, not in parallel. if false then they will be no ordering
* guarantees
* @param the type of the result
* @return a future completed when the blocking code is complete
*/
@GenIgnore(GenIgnore.PERMITTED_TYPE)
Future<@Nullable T> executeBlocking(Callable blockingCodeHandler, boolean ordered);
/**
* Like {@link #executeBlocking(Callable)} but using a callback.
*/
@GenIgnore(GenIgnore.PERMITTED_TYPE)
default void executeBlocking(Callable blockingCodeHandler, Handler> resultHandler) {
Future future = executeBlocking(blockingCodeHandler, true);
if (resultHandler != null) {
future.onComplete(resultHandler);
}
}
/**
* Like {@link #executeBlocking(Callable, boolean)} but using a callback.
*/
@GenIgnore(GenIgnore.PERMITTED_TYPE)
default void executeBlocking(Callable blockingCodeHandler, boolean ordered, Handler> resultHandler) {
Future future = executeBlocking(blockingCodeHandler, ordered);
if (resultHandler != null) {
future.onComplete(resultHandler);
}
}
/**
* Invoke {@link #executeBlocking(Handler, boolean, Handler)} with order = true.
* @param blockingCodeHandler handler representing the blocking code to run
* @param resultHandler handler that will be called when the blocking code is complete
* @param the type of the result
* @deprecated instead use {@link #executeBlocking(Callable)}
*/
@Deprecated
default void executeBlocking(Handler> blockingCodeHandler, Handler> resultHandler) {
executeBlocking(blockingCodeHandler, true, resultHandler);
}
/**
* Same as {@link #executeBlocking(Handler, boolean, Handler)} but with an {@code handler} called when the operation completes
*
* @deprecated instead use {@link #executeBlocking(Callable, boolean)}
*/
@Deprecated
Future<@Nullable T> executeBlocking(Handler> blockingCodeHandler, boolean ordered);
/**
* Same as {@link #executeBlocking(Handler, Handler)} but with an {@code handler} called when the operation completes
*
* @deprecated instead use {@link #executeBlocking(Callable)}
*/
@Deprecated
default Future<@Nullable T> executeBlocking(Handler> blockingCodeHandler) {
return executeBlocking(blockingCodeHandler, true);
}
/**
* Invoke {@link #executeBlocking(Callable, boolean)} with order = true.
* @param blockingCodeHandler handler representing the blocking code to run
* @param the type of the result
* @return a future completed when the blocking code is complete
*/
@GenIgnore(GenIgnore.PERMITTED_TYPE)
default Future<@Nullable T> executeBlocking(Callable blockingCodeHandler) {
return executeBlocking(blockingCodeHandler, true);
}
/**
* If the context is associated with a Verticle deployment, this returns the deployment ID of that deployment.
*
* @return the deployment ID of the deployment or null if not a Verticle deployment
*/
String deploymentID();
/**
* If the context is associated with a Verticle deployment, this returns the configuration that was specified when
* the verticle was deployed.
*
* @return the configuration of the deployment or null if not a Verticle deployment
*/
@Nullable JsonObject config();
/**
* The process args
*/
default List processArgs() {
return VertxCommandLauncher.getProcessArguments();
}
/**
* Is the current context an event loop context?
*
* NOTE! when running blocking code using {@link io.vertx.core.Vertx#executeBlocking(Callable)} from a
* standard (not worker) verticle, the context will still an event loop context and this {@link this#isEventLoopContext()}
* will return true.
*
* @return true if false otherwise
*/
boolean isEventLoopContext();
/**
* Is the current context a worker context?
*
* NOTE! when running blocking code using {@link io.vertx.core.Vertx#executeBlocking(Callable)} from a
* standard (not worker) verticle, the context will still an event loop context and this {@link this#isWorkerContext()}
* will return false.
*
* @return true if the current context is a worker context, false otherwise
*/
boolean isWorkerContext();
/**
* @return the context threading model
*/
ThreadingModel threadingModel();
/**
* Get some data from the context.
*
* @param key the key of the data
* @param the type of the data
* @return the data
*/
T get(Object key);
/**
* Put some data in the context.
*
* This can be used to share data between different handlers that share a context
*
* @param key the key of the data
* @param value the data
*/
void put(Object key, Object value);
/**
* Remove some data from the context.
*
* @param key the key to remove
* @return true if removed successfully, false otherwise
*/
boolean remove(Object key);
/**
* Get some local data from the context.
*
* @param key the key of the data
* @param the type of the data
* @return the data
*/
T getLocal(Object key);
/**
* Put some local data in the context.
*
* This can be used to share data between different handlers that share a context
*
* @param key the key of the data
* @param value the data
*/
void putLocal(Object key, Object value);
/**
* Remove some local data from the context.
*
* @param key the key to remove
* @return true if removed successfully, false otherwise
*/
boolean removeLocal(Object key);
/**
* @return The Vertx instance that created the context
*/
Vertx owner();
/**
* @return the number of instances of the verticle that were deployed in the deployment (if any) related
* to this context
*/
int getInstanceCount();
/**
* Set an exception handler called when the context runs an action throwing an uncaught throwable.
*
* When this handler is called, {@link Vertx#currentContext()} will return this context.
*
* @param handler the exception handler
* @return a reference to this, so the API can be used fluently
*/
@Fluent
Context exceptionHandler(@Nullable Handler handler);
/**
* @return the current exception handler of this context
*/
@GenIgnore
@Nullable
Handler exceptionHandler();
}