001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.util;
028:
029: /**
030: * Provides a rendezvous point and synchronous callback within a
031: * LiveTraceListener. An instance of LiveTraceCallback is installed into a
032: * LiveTracer tracepoint like any other LiveTraceListener. Once installed, the
033: * LiveTrace code calls a listener here, which synchronously calls a callback
034: * established by a test making a call to await(). If a callback isn't
035: * available, the trace listener blocks until one becomes available. After the
036: * callback returns, it is removed. Therefore, while the listener is active,
037: * <b>every</b> trace point must be matched by a call to await(). Otherwise,
038: * the thread being traced will block and all the tests will timeout.
039: *
040: * Sample usage from an i3test:
041: *
042: * <code>
043: * tcb = new LiveTraceCallback();
044: * targetObject.liveTracer.add(TRACE_TAG, tcb);
045: * // initiate some operation that will eventually hit TRACE_TAG
046: * assertTrue(
047: * "trace point was hit",
048: * tcb.await(
049: * new Runnable() {
050: * public void run() {
051: * // stuff executed by the traced thread
052: * }
053: * })
054: * );
055: * </code>
056: */
057: public class LiveTraceCallback implements LiveTraceListener {
058:
059: /**
060: * The default timeout period, in milliseconds.
061: */
062: public static final long DEFAULT_TIMEOUT = 2000L;
063:
064: boolean active = true;
065: Runnable callback = null;
066: Runnable doNothing = new Runnable() {
067: public void run() {
068: }
069: };
070:
071: /**
072: * Called by Display's LiveTracer object after a screen change occurs.
073: */
074: public synchronized void call(String tag) {
075: if (!active) {
076: return;
077: }
078:
079: while (active && callback == null) {
080: try {
081: wait();
082: } catch (InterruptedException ignore) {
083: }
084: }
085:
086: if (active) {
087: callback.run();
088: }
089:
090: callback = null;
091: notifyAll();
092: }
093:
094: /**
095: * Blocks until a tracepoint is reached, causes r.run() to be called
096: * synchronously by the traced thraed, and then lets both the traced
097: * thread and the caller continue. Times out after the indicated timeout
098: * period. If a timeout or interrupt occurs, the callback is cleared
099: * without being called.
100: *
101: * @param r the Runnable whose run() method is to be called
102: * @param timeout timeout period in milliseconds
103: * @return true if the tracepoint was handled normally, false if a timeout
104: * or interrupt occurred
105: */
106: public synchronized boolean await(Runnable r, long timeout) {
107: long deadline = System.currentTimeMillis() + timeout;
108: long remain = timeout;
109: boolean retval = true;
110:
111: callback = r;
112: notifyAll();
113:
114: try {
115: while (callback != null && remain > 0) {
116: wait(remain);
117: remain = deadline - System.currentTimeMillis();
118: }
119:
120: if (callback != null) {
121: System.out
122: .println("LiveTraceCallback.await: timed out");
123: retval = false;
124: }
125: } catch (InterruptedException ie) {
126: System.out.println("LiveTraceCallback.await: interrupted");
127: retval = false;
128: } finally {
129: callback = null;
130: }
131:
132: return retval;
133: }
134:
135: /**
136: * Same as await(r, DEFAULT_TIMEOUT).
137: */
138: public boolean await(Runnable r) {
139: return await(r, DEFAULT_TIMEOUT);
140: }
141:
142: /**
143: * Same as await(<i>do nothing</i>, DEFAULT_TIMEOUT).
144: */
145: public boolean await() {
146: return await(doNothing, DEFAULT_TIMEOUT);
147: }
148:
149: /**
150: * Shuts down this trace listener by arranging for any listener not to
151: * block and instead to be ignored. Any blocked listener is unblocked
152: * and returns without calling the callback, even if one was currently
153: * installed.
154: */
155: public synchronized void shutdown() {
156: active = false;
157: notifyAll();
158: }
159: }
|