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

org.jacpfx.rcp.scheduler.StatelessComponentSchedulerImpl Maven / Gradle / Ivy

There is a newer version: 2.1
Show newest version
/************************************************************************
 *
 * Copyright (C) 2010 - 2014
 *
 * [StatelessComponentSchedulerImpl.java]
 * JACPFX Project (https://github.com/JacpFX/JacpFX/)
 * All rights reserved.
 *
 * 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 org.jacpfx.rcp.scheduler;

import javafx.event.Event;
import javafx.event.EventHandler;
import org.jacpfx.api.component.ComponentHandle;
import org.jacpfx.api.component.StatelessCallabackComponent;
import org.jacpfx.api.component.SubComponent;
import org.jacpfx.api.launcher.Launcher;
import org.jacpfx.api.message.Message;
import org.jacpfx.api.scheduler.StatelessComponentScheduler;
import org.jacpfx.rcp.component.AStatelessCallbackComponent;
import org.jacpfx.rcp.context.Context;
import org.jacpfx.rcp.util.FXUtil;
import org.jacpfx.rcp.worker.StateLessComponentRunWorker;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class StatelessComponentSchedulerImpl implements
        StatelessComponentScheduler, Event, Object> {

    private final Launcher launcher;

    private static final ReadWriteLock lock = new ReentrantReadWriteLock();

    public StatelessComponentSchedulerImpl(final Launcher launcher) {
        this.launcher = launcher;
    }

    @Override
/**
 * {@inheritDoc }
 */
    public final void incomingMessage(
            final Message message,
            final StatelessCallabackComponent, Event, Object> baseComponent) {
        // TODO avoid locking of whole code block
        lock.writeLock().lock();
        try {
            // get active instance
            final SubComponent, Event, Object> comp = this
                    .getActiveComponent(baseComponent);
            final List, Event, Object>> componentInstances = baseComponent
                    .getInstances();
            if (comp != null) {
                if (componentInstances.size() < AStatelessCallbackComponent.MAX_INCTANCE_COUNT) {
                    // create new instance as buffer
                    ComponentHandle handle = baseComponent.getComponent();
                    componentInstances.add(this.getCloneBean(baseComponent,
                            handle.getClass()));
                } // End inner if
                // run component in thread
                this.instanceRun(baseComponent, comp, message);
            } // End if
            else {
                // check if new instances can be created
                if (componentInstances.size() < AStatelessCallbackComponent.MAX_INCTANCE_COUNT) {
                    this.createInstanceAndRun(baseComponent, message);
                } // End if
                else {
                    this.seekAndPutMessage(baseComponent, message);
                } // End else
            } // End else

        } finally {
            lock.writeLock().unlock();
        } // End synchronized
    }

    /**
     * block component, put message to component's queue and run in thread
     *
     * @param baseComponent, the parent component
     * @param comp,          the child component
     * @param message,       the message
     */
    private void instanceRun(
            final StatelessCallabackComponent, Event, Object> baseComponent,
            final SubComponent, Event, Object> comp,
            final Message message) {
        comp.putIncomingMessage(message);
        // TODO switch to embedded worker!!
        baseComponent.getExecutorService().submit(new StateLessComponentRunWorker(
                comp, baseComponent));
    }

    /**
     * if max thread count is not reached and all available component instances
     * are blocked create a new one, block it an run in thread
     *
     * @param baseComponent, the parent component
     * @param message,       the current message
     */
    private void createInstanceAndRun(
            final StatelessCallabackComponent, Event, Object> baseComponent,
            final Message message) {
        ComponentHandle handle = baseComponent.getComponent();
        final StatelessCallabackComponent, Event, Object> comp = this
                .getCloneBean(baseComponent,
                        handle.getClass());
        baseComponent.getInstances().add(comp);
        this.instanceRun(baseComponent, comp, message);
    }

    @SuppressWarnings("unchecked")
    @Override
    /**
     * {@inheritDoc }
     */
    public final , Event, Object>, H extends ComponentHandle> StatelessCallabackComponent, Event, Object> getCloneBean(
            final T baseComponent,
            final Class clazz) {
        final AStatelessCallbackComponent component = AStatelessCallbackComponent.class.cast(baseComponent);
        final Context context = (Context) component.getContext();
        return component.init(this.launcher.getBean(context.getParentId().concat(FXUtil.PATTERN_GLOBAL).concat(context.getId())),context);
    }

    /**
     * Returns a component instance that is currently not blocked.
     *
     * @param baseComponent, the parent component
     * @return an available subcomponent
     */
    private SubComponent, Event, Object> getActiveComponent(
            final StatelessCallabackComponent, Event, Object> baseComponent) {
        final Optional, Event, Object>> result = baseComponent.
                getInstances().
                stream().
                filter(comp -> !comp.isBlocked()).findFirst();
        return result.isPresent() ? result.get() : null;
    }

    /**
     * seek to first running component in instance list and add message to queue
     * of selected component
     *
     * @param baseComponent, the root component
     * @param message,       the current message
     */
    private void seekAndPutMessage(
            final StatelessCallabackComponent, Event, Object> baseComponent,
            final Message message) {
        // if max count reached, seek through component and add
        // message to queue of oldest component
        final SubComponent, Event, Object> comp = baseComponent
                .getInstances().get(this.getSeekValue(baseComponent));
        // put message to queue
        comp.putIncomingMessage(message);
    }

    private int getSeekValue(
            final StatelessCallabackComponent, Event, Object> baseComponent) {
        final AtomicInteger threadCount = baseComponent.getThreadCounter();
        final int seek = threadCount.incrementAndGet()
                % baseComponent.getInstances().size();
        threadCount.set(seek);
        return seek;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy