Deadlines

First submission deadline: 14 September (Demo session on 15 September, see details below)
Final submission deadline: 25 September
To pass this lab you need to register for a demo session on 15 September here. Deadline for registering is 11 September.

Information about how to run the lab remotely or in Windows can be found here.

Lab 1: Trainspotting

In this assignment you will write a program to control two trains. The purpose is to write the program so that the trains move relatively independently of each other, but without colliding. Instead of a real railway, we have a simulator, where one can control the speeds of trains and change rail switches. The simulator gives a signal when a train passes sensors suitably placed on the tracks. It is part of the assignment to decide where sensors should be placed to give sufficient information for your program. The map without sensors looks as follows.

Choice of programming language

In this assignment you must use Java.

Important

In order to make sure you are using the right version of Java and train simulator, you should run

setup_course tda381

on Chalmers GNU/Linux machines.


Assignment

Your assignment is to write a program that controls the trains. The trains should run simultaneously between the two stations (note that each station has two tracks). It is important that the trains are able to move at the same time, and be as independent from each other as possible, without crashing. At the stations the trains should stop and then wait 1 to 2 seconds. The trains should run forever between the stations.

In the beginning there are no sensors on the tracks. You must find where it is suitable to place sensors so that the control program gets the necessary information.

The program that you deliver should work as follows. Each train should be controlled by an independent train program, which runs in its own Java thread. Train programs cannot communicate with outside world by anything else than acquiring and releasing semaphores. In particular, no shared variables should be read or changed by the train programs. Also, both trains must use the same 'train program', and it is not allowed to make the behaviour of a train depend on its train id. For example, the track that a train chooses should not depend on its train id.

Below is a list of more detailed requirements.

Requirements


Train simulator

The simulator is called tsim and with this program you can even modify the train map. You can run tsim as follows:

tsim as a map editor

You need to get your own copy of the map in order to be able to add the sensors. The map you will be working on is that shown above.

The map file is included in the archive in the downloads section.

Then you can start to modify the map with tsim Lab1.map. The figure below shows how to use tsim. You should only select the sensor button in the tools window (the small T-like symbol) and then use the mouse to place sensors on the track.

tsim as a simulator

You may start tsim and interact with it using commands on standard input. Try for example the commands

SetSpeed 1 20
SetSwitch 17 7 RightSwitch

and see what happens. (The second command is necessary for the train to survive the first switch which initially is set in the wrong direction). We provide the Java library to handle the communication with tsim, which lets you change the speed of the trains and the state of the switches in a more convenient way (see next section).

Here are some things to note about the simulator:


Program/Simulator interaction

The simulator and your program run as separate OS processes. They use pipes to communicate. The Main class provided in the skeleton code takes care of joining together the pipes of your solution in Java with the tsim simulator.

All commands between the your program and the simulator are sent line-by-line as text strings, as you saw above. To aid you in your assignment we provide you with a Java library (TSim) that implements the protocol tsim is using. You must use this Java library. The package provides you with an interface to control the behaviour of the trains and switches. You can view the JavaDoc documentation of this library here.

Usage

You cannot create instances of TSimInterface using its constructor, since it is private. Instead you use the static method getInstance() that creates an instance of the class if that has not already been done (singleton pattern).

TSimInterface tsi = TSimInterface.getInstance() ;

Interesting classes

try {
  ...
}
catch (CommandException e) {
  System.err.println(e.getMessage());

  /* If a command failed then something bad has
     happened and we probably don't want to
     continue executing */

  System.exit(1);
}

Downloads

To get started, you need the skeleton code package.

Getting started

You should implement your solution in the Lab1.java file. We provide a Main class which takes care of loading the simulator and connecting it to your solution. You shouldn't need to change this file. This entry point expects at least 3 command line arguments:

  1. map file
  2. speed of train 1
  3. speed of train 2
  4. simulator speed [optional]

Using the command line

To build your solution, you can simply run the following command:

make all

from the root directory of the project. This will place the class files in the bin folder.

You can then run your solution with:

java -cp bin Main Lab1.map 5 15

Using Eclipse

You can also open the files as an Eclipse project:

  1. Extract the trainspotting folder into your workspace directory.
  2. In Eclipse, choose New → Java Project. Give it the exact name trainspotting to use the existing sources.

When running or debugging the Main class in Eclipse, you will need to specify the command-line arguments via the Run Configurations dialog.

Building tsim on your own machine

If you wish to work on this assignment on your own computer, then you will also need to build and run tsim locally. We do not recommend this, since it may not be straightforward, especially if you are not using Linux.

First download the tsim simulator source code. Then build with the following commands:

$ ./configure
$ make
$ make install

The default installation path is /usr/local. If you want to install to some other location instead run ./configure --prefix=/your/location. For more information, see the INSTALL file.


Tips and Tricks

Note!

It was stated above but may be stated again: Reasonable code quality is expected. You are programmers – programming should be an art to you. The quality of your code will be vital for its reuse and maintenance.

Common reasons for rejection

Polling/busy waiting

What is polling and what is not is a hard question. We here give some examples in pseudo code. Loops that reduce to something similar to the situation below (where the dots do not include any blocking wait) must be considered as polling.

while (e) { // POLLING!
   ...
   sleep(t);
   ...
}

Using a blocking operation within a loop is not considered as polling.

while (e) { // NO POLLING!
   ...
   wait(o);
   ...
}

If it is not the case that something is regularly waking the process from its wait. Thus, the following example must be considered as an instance of polling:

obj o;

process a {   
  while (true) {
    sleep(t);
    notify(o);
  }
}

process b {  // POLLING!
  while (e) {
    wait(o);
  }
}


Concurrent Programming 2016 - Chalmers University of Technology & Gothenburg University