eventqueue.jpp

来自「This is a resource based on j2me embedde」· JPP 代码 · 共 708 行 · 第 1/2 页

JPP
708
字号
/* *    * * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. *  * This program 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 version 2 for more details (a copy is * included at /legal/license.txt). *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */package com.sun.midp.events;import com.sun.j2me.security.AccessController;import com.sun.midp.main.*;import com.sun.midp.security.*;import com.sun.midp.log.Logging;import com.sun.midp.log.LogChannels;/** * Contains methods for posting events and registering to receiving events * from both the Java layer and native layer and a dedicated thread * for processing events. Events are processed in the order they were posted. * <p>  * Events can be posted from the native level or posted at * the Java level. When an event is posted at the Java level the event * pre-process method of associated event listener is called and at which time  * the event listener can stop the event from being posted by returning false.  * <p> * The run method of the EventQueue delivers events to event listeners and * polls the native event queue. When there are no events to deliver, * the run method waits after notifying the NativeEventMonitor to wake up * and monitor the native event queue.</p> * <p> * When performing a non-blocking read of a native event, an a empty * event object will be passed to the native method and the native * method will fill in the empty event in one call, saving up to 3 native * method calls per native event over the old stream based * implementation.</p> */public class EventQueue implements Runnable {    /** The global event queue. */    private static EventQueue eventQueue;    /**     * Constructs, assigns a native event queue handle, and     * starts the primary event queue for this isolate.     */    static {        eventQueue = new EventQueue();// #ifndef ENABLE_GCI        eventQueue.nativeEventQueueHandle =            eventQueue.getNativeEventQueueHandle();// #endif ENABLE_GCI        eventQueue.start();    }    /**     * Event queue thread reference to synchronize on. The event queue     * is not used since it given out to callers. But is given to     * the native event queue monitor.     */    Thread eventQueueThread;    /** Next event to dispatch. */    Event nextEvent;    /** Last event in the queue. */    Event lastEvent;    /**     * Holds the event listeners and dispatch data. Each listener     * will be placed at the index equal to the event type ID - 1 it     * registered for (zero is an invalid type). This array will start empty     * and grow if a listener is registered with an event type greater than     * table length - 1 table since 0 is an invalid.     */    DispatchData[] dispatchTable;    /** Number of events in the queue. */    int numEvents; // = 0    /** True, if the queue is alive. */    boolean alive; // = false// #ifndef ENABLE_GCI    /** The thread running the native event monitor. */    Thread eventMonitorThread;    /** A pool for reusing native events. */    NativeEventPool pool;    /** This is for the native finalizer to reset peer native queue. */    int nativeEventQueueHandle = -1;// #endif ENABLE_GCI    /**     * Returns true if the current thread is the event queue dispatch     * thread.     *     * @return true if the current thread is the event queue dispatch thread     */    public static boolean isDispatchThread() {        return (Thread.currentThread() == eventQueue.eventQueueThread);    }    /**     * Get a reference to the event queue in a secure way.     *     * @param token security token with the com.sun.midp permission "allowed"     *     * @return MIDP event queue reference     */    public static EventQueue getEventQueue(SecurityToken token) {        token.checkIfPermissionAllowed(Permissions.MIDP);        return eventQueue;    }    /**     * Get a reference to the event queue in a secure way.     * The calling suite must have the com.sun.midp permission "allowed".     *     * @return MIDP event queue reference     */    public static EventQueue getEventQueue() {        AccessController.checkPermission(Permissions.MIDP_PERMISSION_NAME);        return eventQueue;    }    /**     * Constructs an event queue.  This does not assign a native event queue     * handle. It creates the event threads, but it doesn't start them.     */    EventQueue() {        /*         * Currently we know of 33 events. The table will grow if needed.         * for testing we need to lower that without changing code.         */        int tableSize = 33;        tableSize =            Configuration.getPositiveIntProperty(                "com.sun.midp.events.dispatchTableInitSize", tableSize);        dispatchTable = new DispatchData[tableSize];        eventQueueThread = new Thread(this);// #ifndef ENABLE_GCI        pool = new NativeEventPool();        eventMonitorThread =            new Thread(                new NativeEventMonitor(eventQueueThread, this, pool));// #endif ENABLE_GCI    }// #ifdef ENABLE_GCI    /** Starts the event queue thread. */    void start() {        eventQueueThread.start();    }    /**     * Send a native event to a specific Isolate.     *     * @param event a native event     * @param isolateId ID of the receiving Isolate     */    public void sendNativeEventToIsolate(NativeEvent event,                                         int isolateId) {    	post(event);    }// #else    /** Starts the event queue and event monitor threads. */    void start() {        resetNativeEventQueue();        eventQueueThread.start();        eventMonitorThread.start();    }    /**     * Clears native event queue for a given isolate -      * there could be some events from isolate's previous usage.     */    private native void resetNativeEventQueue();        /**     * Get the handle of the native peer event queue.     *     * WARNING: The native code can handle only one event queue per isolate.     * Only one event queue object in any isolate should have a native handle     * assigned.  If multiple Java event queue objects in the same isolate     * have native handles assigned, this causes serious problems.     *     * @return Native event queue handle     */    private native int getNativeEventQueueHandle();    /**     * Send a native event to a specific Isolate.     *     * @param event a native event     * @param isolateId ID of the receiving Isolate     */    public native void sendNativeEventToIsolate(NativeEvent event,                                                int isolateId);// #endif    /**     * Native finalizer to reset the native peer event queue when     * the Isolate ends.     */// #ifdef ENABLE_CDC    /**     * Queue a shutdown event to the native event queue.     */    private void sendShutdownEvent() {	post(new Event(EventTypes.EVENT_QUEUE_SHUTDOWN));    }// #else    /**     * Queue a shutdown event to the native event queue.     */    private native void sendShutdownEvent();    private native void finalize();// #endif    /**     * Register to preprocess and process events of single type.     *     * @param eventType eventType as an integer as listed in midpEvents.h     * @param listener listener for the event type     *     * @exception IllegalArgumentException if the event type is not positive,     *            or the listener is null     */    public void registerEventListener(int eventType, EventListener listener) {        if (eventType <= 0) {            throw new IllegalArgumentException("Event type is not positive");        }        if (listener == null) {            throw new IllegalArgumentException("Listener is null");        }        synchronized (eventQueueThread) {            if (eventType > dispatchTable.length) {                DispatchData[] newTable = new DispatchData[eventType + 1];                /* Grow the dispatch table. */                for (int i = 0; i < dispatchTable.length; i++) {                    newTable[i] = dispatchTable[i];                }                dispatchTable = newTable;            }            // IMPL_NOTE	    if (Logging.REPORT_LEVEL <= Logging.WARNING) {		if (dispatchTable[eventType - 1] != null) {		    Logging.report(Logging.WARNING, LogChannels.LC_CORE,				   "Warning overwriting event listener");		}	    }            dispatchTable[eventType - 1] = new DispatchData(listener);        }    }    /**     * Post an event to the queue. The reference to the event will be put in     * the queue without copying, so the caller should not reuse events     * passed to this method. The implementation uses a dispatch table     * indexed by event type ID. So if there is no event listener registered     * for event either a <code>NullPointerException</code> or a     * <code>IndexOutOfBoundException</code> will be thrown.     *     * @param event event to post     *     * @exception IndexOutOfBoundsException see method description     * @exception NullPointerException see method description     */    public void post(Event event) {        DispatchData dispatchData;                synchronized (eventQueueThread) {            if (event.type < 1) {                if (Logging.REPORT_LEVEL <= Logging.ERROR) {                    Logging.report(Logging.ERROR,                                   LogChannels.LC_CORE,                                   "Invalid event in the queue.");                }                return;            }            if (event.type > dispatchTable.length) {                if (Logging.REPORT_LEVEL <= Logging.ERROR) {                    Logging.report(Logging.ERROR,                                   LogChannels.LC_CORE,                                   "Cannot dispatch: " +                                   "No listener for this event type: " +                                   event.type);                }                return;            }             if (event.type != EventTypes.EVENT_QUEUE_SHUTDOWN) {                dispatchData = dispatchTable[event.type - 1];                if (dispatchData == null) {                    if (Logging.REPORT_LEVEL <= Logging.ERROR) {                        Logging.report(Logging.ERROR, LogChannels.LC_CORE,                            "Cannot dispatch: " +			    "No listener for this event type: " +			    event.type);                    }                    return;                }                if (!dispatchData.listener.preprocess(event,                        dispatchData.waitingEvent)) {                    /* The listener does not want this event posted. */                    return;                }                dispatchData.waitingEvent = event;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?