Section 30.6 Chapter 30 · Actors and Concurrency 634
The above code shows how changes in a wire’s signal are propagated to any
gates watching it. It’s also important to pass the initial state of a wire to
any observing gates. This only needs to be done once, when the simulation
starts up. After that, gates can simply store the result of the most recent
SignalChanged they have received. Sending out the initial signal when the
simulation starts is as simple as providing a simStarting() method:
override def simStarting() { signalObservers() }
There are now just a few more odds and ends about wires. Wires need
a method for connecting new gates, and they could use a nice toString
method:
def addObserver(obs: Actor) {
observers = obs :: observers
}
override def toString = "Wire("+ name +")"
That is everything you need for wires. Now consider gates, the other major
class of objects in a circuit. There are three fundamental gates that would be
nice to define: And, Or, and Not. All of these share a lot of behavior, so it is
worth defining an abstract Gate class to hold the commonality.
A difficulty in defining this Gate class is that some gates have two input
wires (And, Or) while others have just one (Not). It would be possible to
model this difference explicitly. However, it simplifies the code to think of
all gates as having two inputs, where Not gates simply ignore their second
input. The ignored second input can be set to some dummy wire that never
changes state from false:
private object DummyWire extends Wire("dummy")
Given this trick, the gate class will come together straightforwardly. It
mixes in the Simulant trait, and its one constructor accepts two input wires
and one output wire:
abstract class Gate(in1: Wire, in2: Wire, out: Wire)
extends Simulant {
There are two abstract members of Gate that specific subclasses will have
to fill in. The most obvious is that different kinds of gates compute a dif-
Cover · Overview · Contents · Discuss · Suggest · Glossary · Index