001    package javax.realtime;
002    
003    /** The wait-free queue class facilitate communication and 
004     *  synchronization between instances of <code>RealtimeThread</code>
005     *  and <code>Thread</code>. The problem is that synchronized access
006     *  objects shared between real-time threads and threads might cause
007     *  the real-time threads to incur delays due to execution of the
008     *  garbage collector.
009     *  <p>
010     *  The <code>read()</code> method of this class does not block on an
011     *  imagined queue-empty condition variable. If the <code>read()</code>
012     *  is called on an empty queue null is returned. If two real-time
013     *  threads intend to read from this queue they must provide their
014     *  own synchronization.
015     *  <p>
016     *  The <code>write()</code> method of this queue is synchronized and
017     *  may be called by more than one writer and will block on queue empty.
018     */
019    public class WaitFreeReadQueue {
020    
021        protected boolean notify;
022        protected Object[] readQueue = null;
023        protected int queueSize;
024        protected int currentIndex = 0;
025    
026        protected Thread writerThread = null, readerThread = null;
027        protected MemoryArea memArea;
028    
029        /** A queue with an unsynchronizes and nonblocking <code>read()</code>
030         *  method and a synchronized and blocking <code>write()</code> method.
031         *
032         *  @param writer An instance of <code>java.lang.Thread</code>.
033         *  @param reader An instance of <code>java.lang.Thread</code>.
034         *  @param maximum The maximum number of elements in the queue.
035         *  @param memory The <code>MemoryArea</code> in which this object and
036         *                internal elements are alocated.
037         *  @throws java.lang.IllegalArgumentException
038         */
039        public WaitFreeReadQueue(Thread writer, Thread reader,
040                                 int maximum, MemoryArea memory)
041            throws IllegalArgumentException {
042            writerThread = writer;
043            readerThread = reader;
044            queueSize = maximum;
045            memArea = memory;
046    
047            // TODO (?)
048        }
049    
050        /** A queue with an unsynchronizes and nonblocking <code>read()</code>
051         *  method and a synchronized and blocking <code>write()</code> method.
052         *
053         *  @param writer An instance of <code>java.lang.Thread</code>.
054         *  @param reader An instance of <code>java.lang.Thread</code>.
055         *  @param maximum The maximum number of elements in the queue.
056         *  @param memory The <code>MemoryArea</code> in which this object and
057         *                internal elements are alocated.
058         *  @param notify Whether or not the reader is notified when data is added.
059         *  @throws java.lang.IllegalArgumentException
060         */
061        public WaitFreeReadQueue(Thread writer, Thread reader,
062                                 int maximum, MemoryArea memory,
063                                 boolean notify)
064            throws IllegalArgumentException {
065            this(writer, reader, maximum, memory);
066            this.notify = notify;
067        }
068    
069        /** Set <code>this</code> to empty. */
070        public void clear() {
071            currentIndex = 0;
072        }
073    
074        /** Queries the system to determine if <code>this</code> is empty.
075         *
076         *  @return True, if <code>this</code> is empty. False, if
077         *          <code>this</code> is not empty.
078         */
079        public boolean isEmpty() {
080            return (currentIndex == 0);
081        }
082    
083        /** Queries the system to determine if <code>this</code> is full.
084         *
085         *  @return True, if <code>this</code> is full. False, if
086         *          <code>this</code> is not full.
087         */
088        public boolean isFull() {
089            return (currentIndex == queueSize - 1);
090        }
091    
092        /** Reads the next element in the queue unless the queue is empty.
093         *  If the queue is empty null is returned.
094         *
095         *  @return The instance of <code>java.lang.Object</code> read.
096         *          Null, if <code>this</code> was empty.
097         */
098        public Object read() {
099            if (isEmpty()) return null;
100            else {
101                Object temp = readQueue[0];
102                for (int i = 0; i < currentIndex; i++)
103                    readQueue[i] = readQueue[i+1];
104                currentIndex--;
105                return temp;
106            }
107        }
108    
109        /** Queries the system to determine the number of elements in
110         *  <code>this</code>.
111         *
112         *  @return An integer which is the number of non-empty positions in
113         *          <code>this</code>.
114         */
115        public int size() {
116            return currentIndex;
117        }
118    
119        /** If <code>this</code> is empty <code>waitForData()</code> waits on
120         *  the event until the writer inserts data. Note that true priority
121         *  inversion does not occur since the writer locks a different object
122         *  and the notify is executed by the <code>AsyncEventHandler</code>
123         *  which has <code>noHeap</code> characteristics.
124         */
125        public void waitForData() {
126            // TODO
127        }
128    
129        /** The synchronized and blocking write. This call blocks on queue full
130         *  and will wait until there is space in the queue.
131         *
132         *  @param object The <code>java.lang.Object</code> that is placed in
133         *                <code>this</code>.
134         *  @return True, if the write occured. False, if it did not.
135         *  @throws MemoryScopeException
136         */
137        public synchronized boolean write(Object object) throws MemoryScopeException {
138            while (isFull())
139                try {
140                    Thread.sleep(100);
141                } catch (Exception e) {};
142    
143            readQueue[++currentIndex] = object;
144            return true;
145        }
146    }