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

org.mobicents.commons.event.EventBus Maven / Gradle / Ivy

There is a newer version: 1.0.139
Show newest version
/*
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.mobicents.commons.event;

import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;

import org.apache.log4j.Logger;

import org.mobicents.commons.annotations.NotThreadSafe;
import org.mobicents.commons.annotations.ThreadSafe;

/**
 * @author [email protected] (Thomas Quintana)
 */
@ThreadSafe public final class EventBus {
  private static final Logger logger = Logger.getLogger(EventBus.class);
  private final List dispatchers;
  private final AbstractSet handlers;
  private final BlockingQueue> queue;
  
  private EventBus(final List dispatchers, final Executor executor,
      final AbstractSet handlers, final BlockingQueue> queue) {
    super();
    this.dispatchers = dispatchers;
    this.handlers = handlers;
    this.queue = queue;
    for(final Dispatcher dispatcher : dispatchers) {
      executor.execute(dispatcher);
    }
  }
  
  public static Builder builder() {
    return new Builder();
  }
  
  public boolean contains(final EventHandler handler) {
    return handlers.contains(handler);
  }
  
  public void emit(final Event event) throws InterruptedException {
    queue.put(event);
  }
  
  public void register(final EventHandler handler) {
    handlers.add(handler);
  }
  
  public void terminate() {
    for(final Dispatcher dispatcher : dispatchers) {
      dispatcher.stop();
    }
  }
  
  public void unregister(final EventHandler handler) {
    handlers.remove(handler);
  }
  
  @NotThreadSafe public static final class Builder {
    private Executor executor;
    private int numberOfThreads;
    private int queueSize;
    
    private Builder() {
      super();
      executor = null;
      numberOfThreads = 1;
      queueSize = 10;
    }
    
    public EventBus build() {
      checkNotNull(executor);
      final AbstractSet handlers = new CopyOnWriteArraySet();
      final BlockingQueue> queue = new ArrayBlockingQueue>(queueSize);
      final List dispatchers = new ArrayList();
      for(int counter = 0; counter < numberOfThreads; counter++) {
        dispatchers.add(new Dispatcher(handlers, queue));
      }
      return new EventBus(Collections.unmodifiableList(dispatchers), executor, handlers, queue);
    }
    
    private void checkNotNull(final Executor executor) throws NullPointerException {
  	  if(executor == null) {
        final StringBuilder buffer = new StringBuilder();
        buffer.append("An event bus can not be built with a null value for the executor.\n");
        buffer.append("Please set an executor before calling the build() method on ");
        buffer.append(getClass().getName());
        throw new NullPointerException(buffer.toString());
      }
    }
    
    public Builder setExecutor(final Executor executor) {
      this.executor = executor;
      return this;
    }
    
    public Builder setNumberOfThreads(final int numberOfThreads) {
      this.numberOfThreads = numberOfThreads;
      return this;
    }
    
    public Builder setQueueSize(final int queueSize) {
      this.queueSize = queueSize;
      return this;
    }
  }
  
  private static final class Dispatcher implements Runnable {
    private final AbstractSet handlers;
    private final BlockingQueue> queue;
    
    private volatile boolean dispatching;
    
    private Dispatcher(final AbstractSet handlers,
        final BlockingQueue> queue) {
      super();
      this.dispatching = true;
      this.handlers = handlers;
      this.queue = queue;
    }

	@Override public void run() {
      while(dispatching) {
        Event event = null;
        try {event = queue.take(); }
        catch(InterruptedException ignored) { }
        if(event != null) {
          for(final EventHandler handler : handlers) {
            if(logger.isTraceEnabled()) {
              final StringBuilder buffer = new StringBuilder();
              buffer.append("Processing a(n) event of type ");
              buffer.append(event.getType().toString()).append(".\n");
              buffer.append(event.toString());
              logger.trace(buffer.toString());
            }
            try {
              if(handler.accept(event)) {
                handler.handle(event);
              }
            } catch(final Exception exception) {
              logger.error(exception);
            }
          }
        }
      }
	}
	
	public synchronized void stop() {
	  if(dispatching) { dispatching = false; }
	}
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy