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

com.gh.bmd.jrt.routine.Routine Maven / Gradle / Ivy

There is a newer version: 5.9.0
Show newest version
/*
 * 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 com.gh.bmd.jrt.routine;

import com.gh.bmd.jrt.channel.OutputChannel;
import com.gh.bmd.jrt.channel.ParameterChannel;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * This interface defines the main component of this framework.
 * 

* The interface takes inspiration from the Go routines, where functions are executed * asynchronously and communicate with the external world only through channels. Being Java a * strictly object oriented programming language, the routine itself must be an object based on * logic implemented in other objects. *

* The framework includes a routine class based on the implementation of an invocation interface. * Invocation objects are dynamically instantiated when needed, effectively mimicking the temporary * scope of a function call.
* The paradigm is based on input, result and output channels. A routine can be invoked in * different ways (as explained below). Each routine invocation returns an input channel through * which the caller can pass the input parameters. When all the parameters has been passed, the * input channel is closed and returns the output channel from which to read the invocation * results. At the same time a result channel is passed to the invocation implementation, so that * the output computed from the input parameters can be published outside.
* The advantage of this approach is that the invocation flow can be run in steps, allowing for * continuous streaming of the input data and for abortion in the middle of the execution, without * blocking the running thread for the whole duration of the asynchronous invocation.
* In fact, each channel can abort the execution at any time. *

* The implementing class must provides an automatic synchronization of the invocation member * fields, though, in order to avoid concurrency issues, data passed through the routine channels * should be immutable or, at least, never shared inside and outside the routine.
* Moreover, it is possible to recursively call the same or another routine from inside a routine * invocation in a safe way. Nevertheless, it is always advisable to never perform blocking calls * (such as: reading data from an output channel) in the middle of an execution, since the use * of shared runner instances may lead to unexpected deadlocks. In facts, to prevent deadlock or * starvation issues, it is encouraged the use of finite timeouts when performing blocking calls. *

* The routine object provides three different ways to invoke an execution: *

* Synchronous invocation
* The routine starts an invocation employing a synchronous runner. The result is similar to a * classic method call where the processing completes as soon as the function exits. *

* Asynchronous invocation
* The routine starts an invocation employing an asynchronous runner. In this case the processing * happens in a different thread, while the calling process may go on with its own execution and * perform other tasks. The invocation results can be collected at any time through the output * channel methods. *

* Parallel invocation
* Processing parallelization is the key to leverage the power of multi-core machines. In order to * achieve it, the input data must be divided into subsets which are then processed on different * threads.
* A routine object provides a convenient way to start an invocation which in turn spawns another * invocation for each input passed. This particular type of invocation obviously produces * meaningful results only for routines which takes a single input parameter and computes the * relative output results. *

* It is worth noting how the framework has been designed only through interfaces, so that, * as far as the implementation honors the specific contracts, it is possible to seamlessly combine * different routine implementations. Even the ones coming from third party libraries. *

* Created by davide on 9/7/14. * * @param the input data type. * @param the output data type. */ public interface Routine { /** * Short for invokeAsync().result(). * * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callAsync(); /** * Short for invokeAsync().pass(input).result(). * * @param input the input. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callAsync(@Nullable INPUT input); /** * Short for invokeAsync().pass(inputs).result(). * * @param inputs the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callAsync(@Nullable INPUT... inputs); /** * Short for invokeAsync().pass(inputs).result(). * * @param inputs the iterable returning the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callAsync(@Nullable Iterable inputs); /** * Short for invokeAsync().pass(inputs).result(). * * @param inputs the output channel returning the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callAsync(@Nullable OutputChannel inputs); /** * Short for invokeParallel().result(). *

* This method actually makes little sense, thought it is here for completeness. * * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callParallel(); /** * Short for invokeParallel().pass(input).result(). * * @param input the input. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callParallel(@Nullable INPUT input); /** * Short for invokeParallel().pass(inputs).result(). * * @param inputs the iterable returning the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callParallel(@Nullable INPUT... inputs); /** * Short for invokeParallel().pass(inputs).result(). * * @param inputs the output channel returning the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callParallel(@Nullable Iterable inputs); /** * Short for invokeParallel().pass(inputs).result(). * * @param inputs the output channel returning the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callParallel(@Nullable OutputChannel inputs); /** * Short for invokeSync().result(). * * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callSync(); /** * Short for invokeSync().pass(input).result(). * * @param input the input. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callSync(@Nullable INPUT input); /** * Short for invokeSync().pass(inputs).result(). * * @param inputs the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callSync(@Nullable INPUT... inputs); /** * Short for invokeSync().pass(inputs).result(). * * @param inputs the iterable returning the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callSync(@Nullable Iterable inputs); /** * Short for invokeSync().pass(inputs).result(). * * @param inputs the output channel returning the input data. * @return the output channel. * @throws com.gh.bmd.jrt.common.RoutineException if the execution has been aborted. */ @Nonnull OutputChannel callSync(@Nullable OutputChannel inputs); /** * Invokes the execution of this routine in asynchronous mode. * * @return the invocation parameter channel. */ @Nonnull ParameterChannel invokeAsync(); /** * Invokes the execution of this routine in parallel mode. * * @return the invocation parameter channel. */ @Nonnull ParameterChannel invokeParallel(); /** * Invokes the execution of this routine in synchronous mode. * * @return the invocation parameter channel. */ @Nonnull ParameterChannel invokeSync(); /** * Makes the routine destroy all the cached invocation instances. *

* This method is useful to force the release of external resources when done with the routine. * Note however that the routine will still be usable after the method returns. *

* Normally it is not needed to call this method. */ void purge(); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy