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

delight.concurrency.Concurrent Maven / Gradle / Ivy

The newest version!
package delight.concurrency;

import delight.async.Operation;
import delight.async.Value;
import delight.async.callbacks.SimpleCallback;
import delight.async.callbacks.ValueCallback;
import delight.concurrency.wrappers.SimpleExecutor;
import delight.functional.Closure;

import java.util.ArrayList;
import java.util.List;

public class Concurrent {

    /**
     * Perform these operations sequentially but their own threads to prevent
     * stack overflows.
     * 
     * @param operations
     * @param concurrency
     * @param callback
     */
    public static  void sequential(final List> operations, final Concurrency concurrency,
            final ValueCallback> callback) {

        final Value executor = new Value(null);

        sequentialInt(operations, 0, new ArrayList(operations.size()), concurrency, executor, callback);

    }

    public static  void sequential(final List> operations, final Closure asyncExecutor,
            final ValueCallback> callback) {
        sequentialInt(operations, 0, new ArrayList(operations.size()), asyncExecutor, callback);
    }

    public static  void sequential(final List> operations, final ValueCallback> callback) {
        sequentialInt(operations, 0, new ArrayList(operations.size()), new Closure() {

            @Override
            public void apply(final Runnable o) {
                o.run();
            }

        }, callback);
    }

    private static  void sequentialInt(final List> operations, final int idx, final List results,
            final Closure asyncExecutor, final ValueCallback> callback) {

        if (idx >= operations.size()) {
            callback.onSuccess(results);

            return;
        }

        operations.get(idx).apply(new ValueCallback() {

            @Override
            public void onFailure(final Throwable t) {

                callback.onFailure(t);
            }

            @Override
            public void onSuccess(final R value) {

                if (results.size() > idx) {

                    callback.onFailure(
                            new Exception("Callback for operation was already called: " + operations.get(idx)));
                    return;
                }

                results.add(value);

                if (idx == 0 || idx % 4 != 0) {
                    sequentialInt(operations, idx + 1, results, asyncExecutor, callback);
                    return;
                }

                asyncExecutor.apply(new Runnable() {

                    @Override
                    public void run() {
                        sequentialInt(operations, idx + 1, results, asyncExecutor, callback);
                    }
                });

            }
        });

    }

    private static  void sequentialInt(final List> operations, final int idx, final List results,
            final Concurrency concurrency, final Value executor,
            final ValueCallback> callback) {

        if (idx >= operations.size()) {
            final SimpleExecutor exc = executor.get();
            if (exc == null) {
                callback.onSuccess(results);
                return;
            }

            exc.shutdown(new SimpleCallback() {

                @Override
                public void onFailure(final Throwable t) {
                    callback.onFailure(t);
                }

                @Override
                public void onSuccess() {
                    callback.onSuccess(results);
                }
            });

            return;
        }

        final Value failureReceived = new Value(false);
        final Value successReceived = new Value(false);

        operations.get(idx).apply(new ValueCallback() {

            @Override
            public void onFailure(final Throwable t) {
                if (successReceived.get()) {
                    throw new RuntimeException("Cannot process failure callback <" + t.getMessage() + "> for operation "
                            + operations.get(idx) + ". Success already received.", t);
                }
                if (failureReceived.get()) {
                    System.err.println("Cannot process failure callback for operation " + operations.get(idx)
                            + ". Failure already received.\n  Failure which cannot be processed:\n  <" + t.getMessage()
                            + ">");
                    return;
                }

                failureReceived.set(true);
                callback.onFailure(t);
            }

            @Override
            public void onSuccess(final R value) {

                if (successReceived.get()) {
                    throw new RuntimeException("Cannot process success callback  for operation " + operations.get(idx)
                            + ". Success already received.");
                }
                if (failureReceived.get()) {
                    throw new RuntimeException("Cannot process success callback  for operation " + operations.get(idx)
                            + ". Failure already received.");
                }

                successReceived.set(true);
                if (results.size() > idx) {

                    callback.onFailure(
                            new Exception("Callback for operation was already called: " + operations.get(idx)));
                    return;
                }

                results.add(value);

                if (idx == 0 || idx % 4 != 0) {
                    sequentialInt(operations, idx + 1, results, concurrency, executor, callback);
                    return;
                }
                SimpleExecutor exc = executor.get();

                if (exc == null) {
                    // System.out.println("Create dedicated executor.");

                    exc = concurrency.newExecutor().newAsyncExecutor(this);
                    executor.set(exc);
                }

                exc.execute(new Runnable() {

                    @Override
                    public void run() {
                        sequentialInt(operations, idx + 1, results, concurrency, executor, callback);
                    }
                });

            }
        });

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy