cmiseventqueue.java
来自「CmisJavaApi」· Java 代码 · 共 301 行
JAVA
301 行
/* * The contents of this file are subject to the Dyade Public License, * as defined by the file DYADE_PUBLIC_LICENSE.TXT * * You may not use this file except in compliance with the License. You may * obtain a copy of the License on the Dyade web site (www.dyade.fr). * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific terms governing rights and limitations under the License. * * The Original Code is CmisJava API, including the java package * fr.dyade.cmis, released September 5, 2000. * * The Initial Developer of the Original Code is Dyade. The Original Code and * portions created by Dyade are Copyright Bull and Copyright INRIA. * All Rights Reserved. *//* Copyright 1996-2000 by Institut National de Recherche en Informatique * et en Automatique (INRIA) * All rights reserved. See COPYRIGHT in top-level directory. * * Authors: Laurent Andrey, Eric Dillon, Olivier Festor */// $Id: CMISEventQueue.java,v 1.2 2000/09/05 14:30:30 festor Exp $// $Source: /local/resedas/CVS-Repository/CmisJavaApi/src/fr/dyade/cmis/impl/CMISEventQueue.java,v $//// TODO//// - priority feature ? (i.e several queues and several threads with various priority)// - make a CLEAN sepation between interface and implementation ?package fr.dyade.cmis.impl;import fr.dyade.cmis.api.CMISStack;import fr.dyade.cmis.api.CMISException;import fr.dyade.cmis.api.operation.event.CMISEvent;import fr.dyade.cmis.api.operation.event.CMISEventSource;import fr.dyade.cmis.api.operation.event.InternalErrorEvent;import fr.dyade.cmis.util.TraceManager;/** Event Queue and event dispatcher. * Data structure to keep events generated by transport level (indications, confirmations) or * various asynchronous errors. This class also features a * thread to dispatch event to source and then call the * proper behavior (listener). * * This structure is used by the * {@link CMISStackImpl "generic implementation"}. The same event queue can be shared by * several CMISStack instances: see {@link CMISStackImpl#CMISStackImpl(CMISEventQueue) * dedicated constructor} or concrete implementations ones: * {@link fr.dyade.cmis.rmi.AgentImpl#AgentImpl(String,CMISEventQueue)} or * {@link fr.dyade.cmis.om.OMBinding#OMBinding(CMISEventQueue)}. * * Code sample: * <code> import fr.dyade.cmis.impl.CMISEventQueue; import fr.dyade.cmis.rmi.AgentImpl; import fr.dyade.cmis.om.OMBinding; .... CMISEventQueue commonQueue=new CMISEventQueue(); .... AgentImpl agentrmi=new AgentImpl(registrationName, commonQueue); OMBinding omfmk= new OMBinding(commonQueue); ... </code> * * NOTE: this structure is very alike awt event queue. * * @version cvs $Id: CMISEventQueue.java,v 1.2 2000/09/05 14:30:30 festor Exp $ */public class CMISEventQueue { class CMISEventQueueItem { CMISEvent event; CMISEventQueueItem next; CMISEventQueueItem(CMISEvent evt) { event = evt; } } final class CMISEventDispatchThread extends Thread { private CMISEventQueue theQueue; private boolean doDispatch = true; CMISEventDispatchThread(String name, CMISEventQueue queue) { super(name); theQueue = queue; } /** Stop the thread. * Remark: <tt>Thread.stop()</tt> is deprecated in JDK 1.2. * This method is to be use only be <tt>CMISEventQueue.stopDispatching()</tt>. */ final void stopDispatching() { TraceManager.debugln("stop CMIS event dispatching"); doDispatch = false; interrupt(); // This thread is usually blocked in getNextEvent. //LA: todo: a nice way would be to define a "LastEvent", posted //by the listening "poster" thread(S) & keep track of the registered "posters" for this queue. } final public void run() { // exception reporting via InternalErrorEvent at this place // is not far away from yet another uggly hack (YAUH !). But // life is... while (doDispatch) { CMISEvent event=null; try { event = theQueue.getNextEvent(); theQueue.dispatchEvent(event); } catch (ThreadDeath death) { return; } catch (InterruptedException interruption) { // InterruptedException can occur. See fr.dyade.cmis.om.OMListeningThread.stopDispatching() // nothing we continue, may be this interruption is due to an an update // to the "doDispatch" state variable and so may be this run() method will // complete in a "clean" way. } catch (Throwable other) { // catch any other exception what occurred during event dispatching and processing. // add error handling, but filtering any pb.... try { CMISStackImpl st=(CMISStackImpl)event._getStack(); if (event instanceof InternalErrorEvent) { // DO NOT REPOST TROUBLE ABOUT TROUBLE ! // use last chance handler st.callSynchronousErrorHandler(other); } else { // post an InternalErrorEvent. postUrgentEvent(new InternalErrorEvent(st, other)); } } catch (Throwable other2) { // not InternalErrorEvent post, just last chance handler. try { ((CMISStackImpl)event._getStack()).callSynchronousErrorHandler(other2); } catch (Throwable other3) { if (TraceManager.isDebugOn()) { System.err.println("Bad bad bad Exception occurred during event dispatching:"); other3.printStackTrace(); } } } } } TraceManager.debugln(getClass().getName()+": end run"); } final boolean isDispatching(CMISEventQueue eq) { return theQueue.equals(eq); } final CMISEventQueue getEventQueue() { return theQueue; } } // From Thread.java private static int threadInitNumber; private static synchronized int nextThreadNum() { return threadInitNumber++; } /** Head to event queue. * The actual queue of events, implemented as a linked-list. * We are keeping head and tail (true fifo access). */ CMISEventQueueItem fHead; /** Tail of event queue. */ CMISEventQueueItem fTail; public CMISEventQueue() { fHead = null; fTail = null; String name = "CMIS-EventQueue-" + nextThreadNum(); fDispatchingThread= new CMISEventDispatchThread(name, this); fDispatchingThread.start(); } /** Post a new event at the tail of the queue * @param theEvent the regular event to post. */ public final synchronized void postEvent(CMISEvent theEvent) { CMISEventQueueItem eqi = new CMISEventQueueItem(theEvent); if (fTail == null) { // empty queue fHead = eqi; fTail= eqi; notifyAll(); } else { // tail insertion fTail.next = eqi; fTail=eqi; } } /** Urgent event post (head insertion). * This method is intended to be used to post * {@link fr.dyade.cmis.api.operation.event.InternalErrorEvent} instances. * @param theEvent the urgent event to post. */ public final synchronized void postUrgentEvent( CMISEvent theEvent ) { CMISEventQueueItem eqi = new CMISEventQueueItem(theEvent); if (fTail == null) { // empty queue fHead = eqi; fTail= eqi; notifyAll(); } else { // head insertion eqi.next = fHead; fTail=eqi; } } /** * Remove an event from the queue's head and return it. * This method will * block until an event has been posted by another thread. * @return the next CMISEvent * @exception InterruptedException * if another thread has interrupted this thread. */ public final synchronized CMISEvent getNextEvent() throws InterruptedException { while (fHead == null) { wait(); } CMISEventQueueItem eqi = fHead; fHead = fHead.next; if (fHead==null) { fTail=null; } return eqi.event; } /** * Return the first event without removing it. * @return the first event. */ public final synchronized CMISEvent peekEvent() { return (fHead != null) ? fHead.event : null; } /** * Dispatch an event to its source. * * @param theEvent an instance of CMISEvent, or a * subclass of it. */ final protected void dispatchEvent(CMISEvent event) throws CMISException { ((CMISEventSource)(event.getSource())).dispatchEvent(event); } /** * Remove any pending events for the specified source object. * This method is normally called by the source's removeNotify method. * @param source the object source from which the queue must be clean up for events */ synchronized void removeSourceEvents(Object source) { CMISEventQueueItem entry = fHead; CMISEventQueueItem prev = null; while (entry != null) { if (entry.event.getSource().equals(source)) { if (prev == null) { fHead = entry.next; } else { prev.next = entry.next; } } else { /* LA?: add this else case. When removing entry prev should not change ! */ prev = entry; } entry = entry.next; } fTail=prev; } /** Remove all events related to a stack. * This method remove all event (CMISServiceEvent or CMISServiceRequestEvent) * related to a given stack. Typically this method can be call when a stack is terminated * (association closed). * @param pStack to filter event in the queue. */ public synchronized void removeStackEvents( CMISStack pStack ) { CMISEventQueueItem entry = fHead; CMISEventQueueItem prev = null; while (entry != null) { if (entry.event._getStack()==pStack) { if (prev == null) { fHead = entry.next; } else { prev.next = entry.next; } } else { /* LA?: add this else case. When removing entry prev should not change ! */ prev = entry; } entry = entry.next; } fTail=prev; } public void stopDispatching() { if (fDispatchingThread!=null) { fDispatchingThread.stopDispatching(); } } private CMISEventDispatchThread fDispatchingThread;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?