Package org.eclipse.osgi.framework.eventmgr

Source Code of org.eclipse.osgi.framework.eventmgr.ListenerQueue

/*******************************************************************************
* Copyright (c) 2003, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

package org.eclipse.osgi.framework.eventmgr;

import java.util.ArrayList;
import org.eclipse.osgi.framework.eventmgr.EventListeners.ListElement;
import org.eclipse.osgi.framework.eventmgr.EventManager.EventThread;

/**
* The ListenerQueue is used to snapshot the set of listeners at the time the event
* is fired. The snapshot list is then used to dispatch
* events to those listeners. A ListenerQueue object is associated with a
* specific EventManager object. ListenerQueue objects constructed with the same
* EventManager object will get in-order delivery of events
* using asynchronous delivery. No delivery order is guaranteed for synchronous
* delivery to avoid any potential deadly embraces.
*
* <p>ListenerQueue objects are created as necesssary to build a set of listeners
* that should receive a specific event or events. Once the set is created, the event
* can then be synchronously or asynchronously delivered to the set of
* listeners. After the event has been dispatched for delivery, the
* ListenerQueue object should be discarded as it is likely the list of listeners is stale.
* A new ListenerQueue object should be created when it is time to deliver
* another event.  The memory cost of a ListenerQueue object is
* low since the ListenerQueue object shares the array of listeners with the EventListeners
* object which are queued.
* EventListeners uses copy-on-write semantics for managing the array and will copy the array
* before changing it once the array has been shared with a ListenerQueue. This minimizes
* object creation while guaranteeing the snapshot list is never modified once created.
* @since 3.1
*/
public class ListenerQueue {
  /**
   * EventManager with which this queue is associated.
   */
  protected final EventManager manager;
  /**
   * A list of listener lists.
   */
  private final ArrayList queue;

  /**
   * Once the listener queue has been used to dispatch an event,
   * you cannot add modify the queue.
     * Access to this field must be protected by a synchronized region.
   */
  private boolean readOnly;

  /**
   * ListenerQueue constructor. This method creates an empty snapshop list.
   *
   * @param manager The EventManager this queue is associated with.
   * @throws IllegalArgumentException If manager is null.
   */
  public ListenerQueue(EventManager manager) {
    if (manager == null) {
      throw new IllegalArgumentException();
    }

    this.manager = manager;
    queue = new ArrayList();
    readOnly = false;
  }

  /**
   * Add a listener list to the snapshot list. This method can be called multiple times, prior to
   * calling one of the dispatchEvent methods, to build the set of listeners for the
   * delivery of a specific event. The current list of listeners in the specified EventListeners
   * object is added to the snapshot list.
   *
   * @param listeners An EventListeners object to add to the queue. The current listeners
   * in the EventListeners object will be called when an event is dispatched.
   * @param dispatcher An EventDispatcher object to use when dispatching an event
   * to the listeners on the specified EventListeners.
   * @throws IllegalStateException If called after one of the dispatch methods has been called.
   */
  public synchronized void queueListeners(EventListeners listeners, EventDispatcher dispatcher) {
    if (readOnly) {
      throw new IllegalStateException();
    }

    if (listeners != null) {
      ListElement[] list = listeners.getListeners();

      if (list.length > 0) {
        queue.add(new EventListeners.ListElement(list, dispatcher));
      }
    }
  }

  /**
   * Asynchronously dispatch an event to the snapshot list. An event dispatch thread
   * maintained by the associated EventManager is used to deliver the events.
   * This method may return immediately to the caller.
   *
   * @param eventAction This value is passed to the EventDispatcher.
   * @param eventObject This object is passed to the EventDispatcher.
   */
  public void dispatchEventAsynchronous(int eventAction, Object eventObject) {
    synchronized (this) {
      readOnly = true;
    }
    EventThread eventThread = manager.getEventThread();
    synchronized (eventThread) { /* synchronize on the EventThread to ensure no interleaving of posting to the event thread */
      int size = queue.size();
      for (int i = 0; i < size; i++) { /* iterate over the list of listener lists */
        ListElement list = (ListElement)queue.get(i);
        eventThread.postEvent((ListElement[]) list.primary, (EventDispatcher) list.companion, eventAction, eventObject);
      }
    }
  }

  /**
   * Synchronously dispatch an event to the snapshot list. The event may
   * be dispatched on the current thread or an event dispatch thread
   * maintained by the associated EventManager.
   * This method will not return to the caller until the EventDispatcher
   * has been called (and has returned) for each listener on the queue.
   *
   * @param eventAction This value is passed to the EventDispatcher.
   * @param eventObject This object is passed to the EventDispatcher.
   */
  public void dispatchEventSynchronous(int eventAction, Object eventObject) {
    synchronized (this) {
      readOnly = true;
    }
    // We can't guarantee any delivery order for synchronous events.
    // Attempts to do so result in deadly embraces.
    int size = queue.size();
    for (int i = 0; i < size; i++) { /* iterate over the list of listener lists */
      ListElement list = (ListElement)queue.get(i);
      EventManager.dispatchEvent((ListElement[]) list.primary, (EventDispatcher) list.companion, eventAction, eventObject);
    }
  }
}
TOP

Related Classes of org.eclipse.osgi.framework.eventmgr.ListenerQueue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.