FreeWRL/FreeX3D  3.0.0
WriterThread.java
1 // copyright (c) 1997,1998 stephen f. white
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2, or (at your option)
6 // any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; see the file COPYING. If not, write to
15 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16 
17 package sai.eai;
18 
19 import java.io.IOException;
20 //JAS import java.io.EOFException;
21 //JAS import java.util.Vector;
22 //JAS import java.util.Enumeration;
23 
24 class WriterThread extends Thread {
25  private VFieldOutputStream output;
26  private MessageQueue transientMessages = new MessageQueue();
27  private MessageQueue messages = new MessageQueue();
28  private boolean running;
29  private boolean timerSet;
30  private long timeout;
31  private static final long TIMEOUT = 100;
32  private WriterThreadObserver observer;
33 
34  WriterThread(VFieldOutputStream output, WriterThreadObserver observer) {
35  this.output = output;
36  this.observer = observer;
37  }
38 
39  public void run()
40  {
41  running = true;
42  while (running) {
43  try {
44  synchronized (this) {
45  if (timerSet) {
46  long t = timeout - System.currentTimeMillis();
47  if (t > 0) wait(t);
48  } else {
49  wait();
50  }
51  if (timerSet && System.currentTimeMillis() > timeout) {
52  // move all messages from transient queue to main queue
53  for(;;) {
54  Message msg = transientMessages.dequeue();
55  if (msg == null) break;
56  messages.enqueue(msg);
57  }
58  timerSet = false;
59  }
60  }
61  // send all queued messages
62 
63  // this is outside the synchronized block so that new
64  // messages can come in even if sendMessage() blocks
65  for(;;) {
66  Message msg = messages.dequeue();
67  if (msg == null) break;
68  sendMessage(msg);
69  }
70  } catch (InterruptedException e) {
71  running = false;
72  }
73  }
74  }
75 
76  // this is the main access point to this object -- it enqueues
77  // the given message on the appropriate queue, and wakes up the
78  // sleeping thread
79 
80  public synchronized void send(Message msg)
81  {
82  if (msg.field < 0) {
83  messages.enqueue(msg);
84  } else if (timerSet) {
85  transientMessages.enqueueUnique(msg);
86  } else {
87  messages.enqueue(msg);
88  timeout = System.currentTimeMillis() + TIMEOUT;
89  timerSet = true;
90  }
91  notify();
92  }
93 
94  // secondary access point -- stop the writer thread
95 
96  public synchronized void stopThread()
97  {
98  running = false;
99  notify();
100  }
101 
102  // sendMessage() actually sends a message (woohoo)
103 
104  private void sendMessage(Message message)
105  {
106  try {
107  output.writeInt(message.id);
108  output.writeShort(message.field);
109  output.writeField(message.value);
110  output.flush();
111  } catch (IOException e) {
112  observer.onError(e);
113  }
114  }
115 }