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

org.praxislive.hub.DefaultTaskService Maven / Gradle / Ivy

Go to download

Forest-of-actors runtime supporting real-time systems and real-time recoding - bringing aspects of Erlang, Smalltalk and Extempore to Java.

There is a newer version: 6.0.0-beta1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2023 Neil C Smith.
 * 
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3 only, as
 * published by the Free Software Foundation.
 * 
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * version 3 for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License version 3
 * along with this work; if not, see http://www.gnu.org/licenses/
 * 
 * 
 * Please visit https://www.praxislive.org if you need additional information or
 * have any questions.
 */
package org.praxislive.hub;

import java.lang.System.Logger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.praxislive.base.AbstractRoot;
import org.praxislive.core.Value;
import org.praxislive.core.Call;
import org.praxislive.core.PacketRouter;
import org.praxislive.core.RootHub;
import org.praxislive.core.services.Service;
import org.praxislive.core.services.TaskService;
import org.praxislive.core.services.TaskService.Task;
import org.praxislive.core.types.PError;
import org.praxislive.core.types.PReference;

import static java.lang.System.Logger.Level;

/**
 *
 */
class DefaultTaskService extends AbstractRoot implements RootHub.ServiceProvider {

    private final static Logger LOG = System.getLogger(DefaultTaskService.class.getName());

    private final ExecutorService threadService;
    private final Map, Call> futures;
    private final List completed;

    public DefaultTaskService() {
        threadService = Executors.newCachedThreadPool((Runnable r) -> {
            Thread thr = new Thread(r);
            thr.setPriority(Thread.MIN_PRIORITY);
            return thr;
        });
        futures = new HashMap<>();
        completed = new ArrayList<>();
    }

    @Override
    protected void activating() {
        setRunning();
    }
    
    @Override
    protected void processCall(Call call, PacketRouter router) {
        if (call.isRequest()) {
            try {
                submitTask(call);
            } catch (Exception ex) {
                router.route(call.error(PError.of(ex)));
            }
        }
    }

    @Override
    public List> services() {
        return Collections.singletonList(TaskService.class);
    }

    @Override
    protected void update() {
        for (Future future : futures.keySet()) {
            if (future.isDone()) {
                try {
                    Value value = future.get();
                    Call call = futures.get(future);
                    call = call.reply(value);
                    getRouter().route(call);
                    completed.add(future);
                } catch (Exception ex) {
                    LOG.log(Level.TRACE, "", ex);
                    if (ex instanceof ExecutionException) {
                        Throwable t = ex.getCause();
                        if (t instanceof Exception) {
                            ex = (Exception) t;
                        }
                    }
                    Call call = futures.get(future);
                    call = call.error(PError.of(ex));
                    getRouter().route(call);
                    completed.add(future);
                }
            }
        }
        while (!completed.isEmpty()) {
            futures.remove(completed.get(0));
            completed.remove(0);
        }
    }

    @Override
    protected void terminating() {
        threadService.shutdownNow();
    }

    private void submitTask(Call call) throws Exception {
        List args = call.args();
        if (args.size() == 1) {
            Value arg = args.get(0);
            if (arg instanceof PReference) {
                ((PReference) arg).as(Task.class).ifPresent(task -> {
                    Future future = threadService.submit(task::execute);
                    futures.put(future, call);
                });
            }
        } else {
            throw new IllegalArgumentException();
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy