001/* A subclass of Thread to be used for optimizing reader-writer mechanism in 002 Ptolemy II. 003 004 Copyright (c) 1997-2014 The Regents of the University of California. 005 All rights reserved. 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the above 009 copyright notice and the following two paragraphs appear in all copies 010 of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 028 */ 029package ptolemy.kernel.util; 030 031import java.util.ArrayList; 032import java.util.Iterator; 033import java.util.LinkedList; 034import java.util.List; 035 036/////////////////////////////////////////////////////////////////// 037//// 038 039/** PtolemyThread 040 PtolemyThread extends Thread by adding rudimentary debugging capability. 041 042 @author Lukito Muliadi, contributor: Edward A. Lee 043 @version $Id$ 044 @since Ptolemy II 0.2 045 @Pt.ProposedRating Green (lmuliadi) 046 @Pt.AcceptedRating Green (liuj) 047 */ 048public class PtolemyThread extends Thread implements Debuggable { 049 /** Construct a new PtolemyThread object. This constructor has the 050 * same effect as PtolemyThread(null, null, <i>generatedName</i>), where 051 * <i>generatedName</i> is a newly generated name. Automatically generated 052 * names are of the form "Thread-"+n, where n is an integer. 053 */ 054 public PtolemyThread() { 055 super(); 056 } 057 058 /** Construct a new PtolemyThread object. This constructor has the same 059 * effect as PtolemyThread(null, target, <i>generatedName</i>), where 060 * <i>generatedName</i> is a newly generated name. Automatically generated 061 * names are of the form "Thread-"+n, where n is an integer. 062 * @param target The object whose run method is called. 063 */ 064 public PtolemyThread(Runnable target) { 065 super(target); 066 } 067 068 /** Construct a new PtolemyThread object. This constructor has the 069 * same effect as PtolemyThread(null, target, name) 070 * @param target The object whose run method is called. 071 * @param name The name of the new thread. 072 * 073 */ 074 public PtolemyThread(Runnable target, String name) { 075 super(target, name); 076 } 077 078 /** Construct a new PtolemyThread object. This constructor has the 079 * same effect as PtolemyThread(null, null, name) 080 * @param name The name of the new thread. 081 */ 082 public PtolemyThread(String name) { 083 super(name); 084 } 085 086 /** Construct a new PtolemyThread object. This constructor has the 087 * same effect as PtolemyThread(group, target, generatedName), 088 * where generatedName is a newly generated name. Automatically 089 * generated names are of the form "Thread-"+n, where n is an 090 * integer. 091 * @param group The thread group 092 * @param target The object whose run method is called. 093 */ 094 public PtolemyThread(ThreadGroup group, Runnable target) { 095 super(group, target); 096 } 097 098 /** Construct a new PtolemyThread object so that it has target as 099 * its run object, has the specified name as its name, and belongs 100 * to the thread group referred to by group. 101 * @param group The thread group. 102 * @param target The object whose run method is called. 103 * @param name The name of the new thread. 104 * @exception SecurityException If the superclass constructor throws it. 105 * 106 */ 107 public PtolemyThread(ThreadGroup group, Runnable target, String name) { 108 super(group, target, name); 109 } 110 111 /** Construct a new PtolemyThread object. This constructor has the same 112 * effect as PtolemyThread(group, null, name). 113 * @param group The thread group. 114 * @param name The name of the new thread. 115 */ 116 public PtolemyThread(ThreadGroup group, String name) { 117 super(group, name); 118 } 119 120 /////////////////////////////////////////////////////////////////// 121 //// public methods //// 122 123 /** Append a listener to the current set of debug listeners. 124 * If the listener is already in the set, do not add it again. 125 * @param listener The listener to which to send debug messages. 126 * @see #removeDebugListener(DebugListener) 127 * @since Ptolemy II 2.3 128 */ 129 @Override 130 public synchronized void addDebugListener(DebugListener listener) { 131 if (_debugListeners == null) { 132 _debugListeners = new LinkedList(); 133 } else { 134 if (_debugListeners.contains(listener)) { 135 return; 136 } 137 } 138 139 _debugListeners.add(listener); 140 _debugging = true; 141 } 142 143 /** Unregister a debug listener. If the specified listener has not 144 * been previously registered, then do nothing. 145 * @param listener The listener to remove from the list of listeners 146 * to which debug messages are sent. 147 * @see #addDebugListener(DebugListener) 148 * @since Ptolemy II 2.3 149 */ 150 @Override 151 public synchronized void removeDebugListener(DebugListener listener) { 152 if (_debugListeners == null) { 153 return; 154 } 155 156 _debugListeners.remove(listener); 157 158 if (_debugListeners.size() == 0) { 159 _debugging = false; 160 } 161 162 return; 163 } 164 165 /////////////////////////////////////////////////////////////////// 166 //// protected methods //// 167 168 /** Send a debug event to all debug listeners that have registered. 169 * @param event The event. 170 * @since Ptolemy II 2.3 171 */ 172 protected final void _debug(DebugEvent event) { 173 if (_debugging) { 174 // We copy this list to that responding to the event may block. 175 // while the execution thread is blocked, we want to be able to 176 // add more debug listeners... 177 // Yes, this is slow, but hey, it's debug code. 178 List list; 179 180 synchronized (this) { 181 list = new ArrayList(_debugListeners); 182 } 183 184 Iterator listeners = list.iterator(); 185 186 while (listeners.hasNext()) { 187 ((DebugListener) listeners.next()).event(event); 188 } 189 } 190 } 191 192 /** Send a debug message to all debug listeners that have registered. 193 * By convention, messages should not include a newline at the end. 194 * The newline will be added by the listener, if appropriate. 195 * Note that using this method could be fairly expensive if the 196 * message is constructed from parts, and that this expense will 197 * be incurred regardless of whether there are actually any debug 198 * listeners. Thus, you should avoid, if possible, constructing 199 * the message from parts. 200 * @param message The message. 201 * @since Ptolemy II 2.3 202 */ 203 protected final void _debug(String message) { 204 if (_debugging) { 205 // We copy this list to that responding to the event may block. 206 // while the execution thread is blocked, we want to be able to 207 // add more debug listeners... 208 // Yes, this is slow, but hey, it's debug code. 209 List list; 210 211 synchronized (this) { 212 list = new ArrayList(_debugListeners); 213 } 214 215 Iterator listeners = list.iterator(); 216 217 while (listeners.hasNext()) { 218 ((DebugListener) listeners.next()).message(message); 219 } 220 } 221 } 222 223 /////////////////////////////////////////////////////////////////// 224 //// protected variables //// 225 226 /** Flag that is true if there are debug listeners. 227 * @since Ptolemy II 2.3 228 */ 229 protected volatile boolean _debugging = false; 230 231 /** The list of DebugListeners registered with this object. 232 * @since Ptolemy II 2.3 233 */ 234 protected LinkedList _debugListeners = null; 235}