View Javadoc
1   package org.metricshub.jawk.jrt;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2025 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import java.util.HashSet;
26  import java.util.LinkedList;
27  import java.util.List;
28  import java.util.Set;
29  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
30  
31  /**
32   * An item which blocks until something useful can be
33   * done with the object. The BlockManager multiplexes
34   * BlockObjects such that unblocking one
35   * BlockObject causes the BlockManager to dispatch
36   * the notifier tag result of the BlockObject.
37   * <p>
38   * BlockObjects are chained. The BlockManager
39   * blocks on all chained BlockObjects until one
40   * is unblocked.
41   * <p>
42   * Subclasses must provide meaningful block()
43   * and getNotifierTag() routines.
44   * <p>
45   * BlockObjects do not actually perform the client
46   * blocking. This is done by the BlockManager at the
47   * AVM (interpreted) or compiled runtime environment.
48   * The AVM/compiled environments make special provision
49   * to return the head block object to the BlockManager
50   * (within _EXTENSION_ keyword processing).
51   *
52   * @see BlockManager
53   * @author Danny Daglas
54   */
55  public abstract class BlockObject {
56  
57  	private BlockObject nextBlockObject = null;
58  
59  	/**
60  	 * <p>
61  	 * Constructor for BlockObject.
62  	 * </p>
63  	 */
64  	protected BlockObject() {}
65  
66  	/**
67  	 * Construct a meaningful notifier tag for this BlockObject.
68  	 *
69  	 * @return a {@link java.lang.String} object
70  	 */
71  	public abstract String getNotifierTag();
72  
73  	/**
74  	 * Block until meaningful data is made available for
75  	 * the client application. This is called by the BlockManager
76  	 * in a way such that the BlockManager waits for one
77  	 * BlockObject to unblock.
78  	 *
79  	 * @throws java.lang.InterruptedException if any.
80  	 */
81  	public abstract void block() throws InterruptedException;
82  
83  	/**
84  	 * Eliminate the rest of the BlockObject chain.
85  	 */
86  	public final void clearNextBlockObject() {
87  		this.nextBlockObject = null;
88  	}
89  
90  	/**
91  	 * Chain this BlockObject to another BlockObject.
92  	 * The chain is linear and there is no upper bounds on
93  	 * the number of BlockObjects that can be supported.
94  	 *
95  	 * @param bo a {@link org.metricshub.jawk.jrt.BlockObject} object
96  	 */
97  	@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Block chain uses direct references between block objects")
98  	public void setNextBlockObject(BlockObject bo) {
99  		this.nextBlockObject = bo;
100 	}
101 
102 	/**
103 	 * <p>
104 	 * Getter for the field <code>nextBlockObject</code>.
105 	 * </p>
106 	 *
107 	 * @return a {@link org.metricshub.jawk.jrt.BlockObject} object
108 	 */
109 	protected final BlockObject getNextBlockObject() {
110 		return nextBlockObject;
111 	}
112 
113 	/**
114 	 * Obtain all chained BlockObjects as a List,
115 	 * including this one.
116 	 * A BlockObject chain cycle causes a runtime exception
117 	 * to be thrown.
118 	 *
119 	 * @return A List of chained BlockObjects, including
120 	 *         this one.
121 	 * @throws org.metricshub.jawk.jrt.AwkRuntimeException if the BlockObject
122 	 *         chain contains a cycle.
123 	 */
124 	public List<BlockObject> getBlockObjects() {
125 		List<BlockObject> retval = new LinkedList<BlockObject>();
126 		Set<BlockObject> blockObjects = new HashSet<BlockObject>();
127 		BlockObject ref = this;
128 		while (ref != null) {
129 			if (blockObjects.contains(ref)) {
130 				throw new AwkRuntimeException(
131 						"Block chain contains a cycle (duplicate) : " + ref.getClass().getName() + " / " + ref.getNotifierTag());
132 			} else {
133 				blockObjects.add(ref);
134 			}
135 			retval.add(ref);
136 			ref = ref.getNextBlockObject();
137 		}
138 		return retval;
139 	}
140 
141 	/**
142 	 * {@inheritDoc}
143 	 * Ensure non-evaluation of a BlockObject by throwing an AWK Runtime
144 	 * exception, in case it leaks into AWK evaluation space.
145 	 */
146 	@Override
147 	public final String toString() {
148 		throw new AwkRuntimeException("Extension Violation : Cannot AWK-evaluate a BlockObject.");
149 	}
150 }