Concurrent Programming Course

Assignment 3: Tea Shop Simulation

The Problem

The Owner of a Tea Shop suspects that the way in which the Shop is operated means that customers have to spend too much time waiting to be served, and so tend to go elsewhere instead. In order to evaluate the situation, a simulation of the Shop has been commissioned. Initially this simulation will simply run with text output describing the events as they occur in the Shop, and collect a minimal amount of statistical data.

Intention of assignment

The simulation is valuable to the Owner, but note that there are much better techniques for simulating than writing a concurrent program. The purpose of this assignment is to teach you to write a program in which synchronization and communication take place between several concurrent processes. It is intended to force you to solve (and not simply avoid) a range of interesting synchronisation problems.

Choice of programming language

You may solve this assignment using either Erlang or JR.

Synchronisation constructs

For synchronisation you are only allowed to use message passing. Students doing the lab in Erlang will notice that it is very easy to stick to this rule, as Erlang is built entirely around message passing.


The Tea Shop

The Shop consists of a clock, the owner, a chef, and a number of customers. The Shop is operated by the owner and chef, whose job is to make and serve tea to the customers, who order at the Bar in a first-come-first-served manner. Each customer may only order a single cup at one time. The owner and chef can each serve only a single customer at a time, although others may be waiting to be served.

The owner and chef

  • There is one shared order queue served by both the owner and the chef.
  • The owner or the chef will refuse to serve any customer ordering after closing time.
  • If it is not closing time, the owner and chef serve customers independently. Customers can only order tea, which is served in disposable cups not tracked by the simulation.
  • The chef leaves at closing time. The owner will not leave the Shop until all others (customers and chef) have left the Shop.

    The owner

    • At ten-minutes before closing time the owner will be alerted by the Clock and calls last orders to warn the customers that closing time is soon.
    • The owner may finish serving any customer order he started before attending to the “last orders call
    • .

The Door

  • The customers enter the Shop at regular time intervals spread throughout the lifetime of the simulation.

The Customers

  • On entering the Shop, each customer will order a cup of tea, which will be served by either the owner or the chef.
  • When they've been served, customers will drink their tea. The drinking is assumed to take a set time.
  • When they've finished their tea, customers go back to the bar to order another cup. This goes on until the customer has drunk a set number of cups (configured at compile time), or the owner refuses to serve the customer because it is after closing time. In either case, the customer will leave the Shop straight away.
  • Some of the customers exhibit the following additional behavior: when they hear the owner call "last orders", if they are not currently drinking the last of their set number of cups, they will finish their current cup instantly and go to the bar to order one and only one more. Make sure to carefully read the details of this point in the “last orders” section.

The Clock

You do not have to write a clock yourself. You must use the following class. clock.erl implements the clock which keeps track of the time in the simulation. See source code documentation for how to use it.

The clock in the bar serves two purposes:

  • It will alert the owner of both “last orders” and “closing time”. The owner will alert his customers when it is time for last orders.
  • The clock serves and updates the current time that each process uses to print their actions.

The Statistics

At the end of the simulation, i.e. when all other processes have terminated cleanly, the owner must print the number of customers created, and entered/left the Shop. You may print additional statistics, but it is not a requirement:

  • Maximum/Average/Minimum waiting time for a customer when ordering.

  • Number of orders, accepted orders, refused orders.

  • Number of orders accepted after the last order call.

  • Number of customers that react to the last order call, and how many get accepted/refused.


The Last Orders Problem

Callback solution - recommended

Every customer that comes into the Shop says “Hello” to the owner and hands over a reference to itself to the owner (who stores it in some data structure). When they leave the Shop, they say goodbye to the owner, so he can remove that reference.

Unacceptable solutions

"Before you start drinking, calculate the time left until last call, and do not sleep longer than that".
You might think this is a good idea, but this way is not very realistic. In concurrent programming, you hardly ever know in advance when things will happen. Using this solution, you wouldn't learn anything useful.
The customers must be informed by the owner that it is time for last orders!
This solution is NOT acceptable.

Remember that you are only allowed to use message passing in this lab, so for example using shared variables other than channels is not an option!


Requirements

Submitting

When submitting, you must provide the following.

  • documentation.txt (the ASCII text file containing your documentation)
  • All your source code (*.erl) files necessary to compile and run your solution except clock.erl

Do not include uncessary files such as hidden files (.*), or compiled Erlang code (*.beam files).

Documentation

You must document your solution with an ASCII text file. The documentation is intended as a description of your solution – do not translate your code into English. The documentation should include everything needed for easy understanding of the solution. In particular we demand that your documentation contains:

  • An overview of your solution by explaining what your classes do and how they relate to each other.
  • Is there any possibility of deadlock in your solution ? Why (not) ?

Source Code

  • The code structure has to be clear (even visually – use of indentation and newlines where appropriate) and should not be hidden in extensive documentation of trivialities ("this is an assignment of A to B"). Especially the call structure has to be either obvious or documented.
  • The code must use helpful variable, data structure and function names. If uncertain, use code comments to describe how the name is used at the point of declaration.
  • In order to see what is happening when running the simulation you must have output from the Customers, the owner, and the chef reporting all important events that occur.
  • Split your functionality into sensible modules; one for the owner, one for the customers, and so on. Remember, modules are declared as follows:
    -module(module_name).
    -export([some_unary_function/1, some_binary_function/2, ...]).
    
    %% Code goes here
    
  • All processes (except the ones in the clock, and the process executing the main method) must include its process ID when printing from all processes. This will make it possible to see which process is actually printing, compared to just writing the name of the process one thinks is printing.

    Printing must contain the current time (from the clock) and which process is doing the printing. You must determine which process is doing the printing by using self().

    Here is an example of how it could look:

    print(Msg) ->
      io:format("Process ~w at ~w: ~s~n", [self(), clock:get_time(), Msg]).

You must not

  • Kill a process.
  • Resolve communication with an all-purpose one-channel solution.

Observations

  • The present lab can be taken to mean that the owner and chef make tea in zero time. If so, the owner will be too fast, and there will be little interleaving of actions between the two serving guys; we want to see customers stuck at the bar.
  • Since we only serve tea, it would be nicer if customers were dynamic in their behavior. As of now, “..customer has drunk a set number of cups (configured at compile time)” suggests a constant behavior for all of them.
  • You may wish to explore these issues and change your code accordingly, but this is not required to pass the lab.

Tips and Tricks

  • Run your program without customers entering the Shop. This will work if your solution is correct. The solution should not be dependent on the events created by the customers.
  • It is not necessary for a processes to do multiple tasks at the same time. e.g when the owner takes an order, it is not necessary to listen for more messages to do other tasks while handling the order (which takes some time).
  • Use short delay times – there is no need for a simulation run to take more than 20–30 seconds.

Thanks

This is a simplification of the Pub lab, which was used in previous years of this course.

Last modified: [an error occurred while processing this directive]
COMPUTER SCIENCE AND ENGINEERING - Chalmers University of Technology and Göteborg University
SE-412 96 Göteborg, Sweden - Tel: +46 (0)31- 772 1000