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

org.smallmind.phalanx.worker.WorkManager Maven / Gradle / Ivy

There is a newer version: 2.4.5
Show newest version
/*
 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 David Berkman
 * 
 * This file is part of the SmallMind Code Project.
 * 
 * The SmallMind Code Project is free software, you can redistribute
 * it and/or modify it under either, at your discretion...
 * 
 * 1) The terms of GNU Affero General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * ...or...
 * 
 * 2) The terms of the Apache License, Version 2.0.
 * 
 * The SmallMind Code Project 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
 * General Public License or Apache License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * and the Apache License along with the SmallMind Code Project. If not, see
 *  or .
 * 
 * Additional permission under the GNU Affero GPL version 3 section 7
 * ------------------------------------------------------------------
 * If you modify this Program, or any covered work, by linking or
 * combining it with other code, such other code is not for that reason
 * alone subject to any of the requirements of the GNU Affero GPL
 * version 3.
 */
package org.smallmind.phalanx.worker;

import java.lang.reflect.Array;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.atomic.AtomicReference;
import org.smallmind.instrument.ChronometerInstrument;
import org.smallmind.instrument.InstrumentationManager;
import org.smallmind.instrument.MetricProperty;
import org.smallmind.instrument.config.MetricConfiguration;
import org.smallmind.instrument.config.MetricConfigurationProvider;
import org.smallmind.scribe.pen.LoggerManager;

public class WorkManager, T> implements MetricConfigurationProvider {

  private final AtomicReference stateRef = new AtomicReference<>(State.STOPPED);
  private final MetricConfiguration metricConfiguration;
  private final TransferQueue transferQueue;
  private final Class workerClass;
  private final int concurrencyLimit;
  private W[] workers;
  public WorkManager (MetricConfiguration metricConfiguration, Class workerClass, int concurrencyLimit) {

    this.metricConfiguration = metricConfiguration;
    this.workerClass = workerClass;
    this.concurrencyLimit = concurrencyLimit;

    transferQueue = new LinkedTransferQueue<>();
  }

  public int getConcurrencyLimit () {

    return concurrencyLimit;
  }

  @Override
  public MetricConfiguration getMetricConfiguration () {

    return metricConfiguration;
  }

  public void startUp (WorkerFactory workerFactory)
    throws InterruptedException {

    if (stateRef.compareAndSet(State.STOPPED, State.STARTING)) {

      workers = (W[])Array.newInstance(workerClass, concurrencyLimit);
      for (int index = 0; index < workers.length; index++) {

        Thread workerThread = new Thread(workers[index] = workerFactory.createWorker(metricConfiguration, transferQueue));

        workerThread.setDaemon(true);
        workerThread.start();
      }

      stateRef.set(State.STARTED);
    } else {
      while (State.STARTING.equals(stateRef.get())) {
        Thread.sleep(100);
      }
    }
  }

  public void execute (final T work)
    throws Exception {

    if (!State.STARTED.equals(stateRef.get())) {
      throw new WorkManagerException("%s is not in the 'started' state", WorkManager.class.getSimpleName());
    }

    InstrumentationManager.execute(new ChronometerInstrument(this, new MetricProperty("event", MetricType.ACQUIRE_WORKER.getDisplay())) {

      @Override
      public void withChronometer ()
        throws InterruptedException {

        boolean success;

        do {
          success = transferQueue.tryTransfer(work, 1, TimeUnit.SECONDS);
        } while (!success);
      }
    });
  }

  public void shutDown ()
    throws InterruptedException {

    if (stateRef.compareAndSet(State.STARTED, State.STOPPING)) {
      for (W worker : workers) {
        try {
          worker.stop();
        } catch (Exception exception) {
          LoggerManager.getLogger(WorkManager.class).error(exception);
        }
      }
      stateRef.set(State.STOPPED);
    } else {
      while (State.STOPPING.equals(stateRef.get())) {
        Thread.sleep(100);
      }
    }
  }

  private static enum State {STOPPED, STARTING, STARTED, STOPPING}
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy