XML

kent logo

CO538 Anonymous Questions and Answers

This page lists the various questions and answers. To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.

We have taken the liberty of making some minor typographical corrections to some of the questions as originally put. Although most of the questions here will have been submitted anonymously, this page also serves to answer some questions of general interest to those on the course.

When asking questions, please do not simply paste in your code and ask what is wrong with it, as these types of question are hard to answer in a public forum (resulting in either no answer, or an answer which will only be of use to the person asking the question). In many cases, a question about code can be formulated in general terms. For example, if you have an `IF' block that results in an `incorrect indentation' error, you might ask, ``what is the correct syntax for an occam `if' statement ?''. Questions of this form are easier to answer, and are meaningful to all.

Questions that are not suitable for these public pages (i.e. those that contain assignment-specific code), should be mailed to your seminar-leader.


Question 61:

Hi. If we receive a poison should we output it? It is not too clear in the question how the program should terminate. Could you clarify please.

Answer 61:

The higher-level protocol used on NAME.NUMBER channels is that, most of the time, only string variants flow. A poison variant only gets sent once and is the last item to be sent down the channel.

A process receiving poison should take that as a hint to die, tidying up any outstanding business first. That business might include outputting more string variant(s) on its output and, finally, a poison variant - so that the next process in the pipeline knows that it, also, should terminate.

You should notice that the given processes, read.data and display, both behave in this way. So should your processes. Then, all the processes in your system will terminate cleanly when all the data has been processed and your whole program will end.

All of the above will have been discussed in your seminar groups earlier this term.

Keywords: q6 , poison

Referrers: Question 55 (2003)


Question 62:

Could you please help me with reading in the protocols for Q6. From looking at the notes on 10-21, I have worked out it is a tagged protocol. Here is the code that I have written:

  SEQ
    ok := TRUE
    WHILE TRUE
      in ? CASE
        INT size:
        string; size::name; mark
        poison
          ok := FALSE

But I get errors with incorrect indentation. I'm presuming that this is not the problem. And there is something wrong with what I have written. If I comment out the string line, it compiles - but with it in, it does not. I'm not sure how to read in the string tag. Is what I have written completly wrong? Any pointers please!

Answer 62:

Well, I should just refer you to the answers to Question 57 (2000) and Question 53 (2000) ...

However, each tagged variant in a CASE input requires a response - the action to be performed if you get that variant. That response is written in some code that has to be indented, as usual, just after the line inputting that variant. In the above, you have such a line for the poison variant, but not for the string one. So, the compiler correctly complains that the line following that string variant is incorrectly indented - it should be your response to the input. For example:

  SEQ
    ok := TRUE
    WHILE TRUE
      in ? CASE
        INT size:
        string; size::name; mark
          SKIP  -- >>>>>>>>> maybe a fuller response should be here ...
        poison
          ok := FALSE

Keywords: q6 , incorrect-indentation


Question 63:

A note on the diagrams needed in our submission for question 6. The diagram for q6.occ is already in the file - so obviously we don't have to reproduce that. And the diagram for cells is so small and just shows the obvious. Do we definitely have to include a diagram?

Answer 63:

No - for the reasons you state and for this submission only, you do not have to include a data-flow diagram.

Further, to save paper, you may delete the documentation I supplied from the program listing you print out. Make sure you still print a complete program and include your own documentation for the modifications you have made.

Keywords: q6 , diagrams


Question 64:

I am looking at some of the past papers and have a couple of questions about one of the questions. It asks you to explain the synchronisation of a channel? But all it has in the notes about synchronising is:

              input synchronising  =  input ? x

and the same for output. Is this all it means or is there more? Thanks.

Answer 64:

This is a pretty fundamental issue. If you don't know the answer, then you cannot have been following the course and will not be able to appreciate how any of the exercises or examples work. More likely, you have just been thrown by terminology and really do understand the concepts.

The basic facts of channel synchronisation are given in slides 4-27 through 4-31. This is repeated in sections 3.2 and 3.3 of the "occam2 Checklist" paper in your notes. The idea is assumed by almost everything else in the course.

Keywords: channels , synchronisation


Question 65:

Can you explain "without using ALT constructs" a buffered channel with a max capacity of 100 items? Does the question mean a buffered channel like a ring buffer??

Answer 65:

No - the serial ring buffer process (slides 6-11 through 6-13) requires an ALT. The sought answer is the parallel piepline of id processes (slides 5-7 and 6-17).

Keywords: buffered-channel , alternation

Referrers: Question 123 (2003)


Question 66:

For question 7, I am trying to draw a boarder for the dining philosophers room. I can do it with lots of cursor.x.y and out.string procedures but this seems time consuming. I thought of doing it in a replicated PAR or replicated SEQ and I wrote this code:

  #INCLUDE "consts.inc"
  #USE "course.lib"

  PROC a (CHAN OF BYTE out)
    PAR i = 1 FOR 26
      SEQ
        cursor.x.y (4, i, out)
        out.string ("#", 0, out)
  :

  PROC test (CHAN OF BYTE keyboard, screen, error)
    PAR
      a (screen)
      ...  other things
  :

But when I compile it, it says there is a type mismatch in parameter 2 of cursor.x.y. This is the y coordinate that I am changing so that the character gets printed on the line below the first one to create a column like this:

      #
      #
      #
      #
      #
      #

Why does the compiler not like the second parameter of the cursor.x.y proceedure? Doesen't it just need to be a number?

Answer 66:

The second parameter of cursor.x.y needs to be a BYTE. Replicator control variables (e.g. your i) are INTs. You need to cast it into a BYTE:

        cursor.x.y (4, BYTE i, out)

See the answer to Question 7 (2000) for information on casting between occam types.

Your PAR replicator also won't work because it implies parallel outputs to the out channel - illegal! So it has to be a SEQ replicator. In any case, unless the occam kernel supports, and is running on a multiprocessor machine, the SEQ replicator for code like this will be faster than a PAR (which will have to startup and shutdown 25 software processes).

Your code would also be slightly snappier with:

  PROC a (CHAN OF BYTE out)
    SEQ
      cursor.x.y (4, 1, out)
      SEQ i = 1 FOR 26            -- the "2" could be anything though
        SEQ
          out ! '#'               -- don't need out.string for a single char
          cursor.down (1, out)
          cursor.left (1, out)
      out ! FLUSH

Keywords: q7 , type-mismatch , cast , cursor

Referrers: Question 32 (2012) , Question 21 (2001) , Question 74 (2000)


Question 67:

How do I create a replicated protocol CASE statement for the dining philosophers. I have written:

  PROC display ([]CHAN OF MYPROTOCOL reportin, CHAN OF BYTE out)
    WHILE TRUE
      ALT i = 0 FOR 10
        INT n:
        reportin[i]? CASE
          thinking
            out.string ("Philosopher Sat Down", 50, out)
          hungry
            out.string ("Philosopher is hungry", 50, out)
          etc...
  :

But I keep getting incorrect indentation errors. Do I need any SEQ or PARs here or is the problem elsewhere?

Answer 67:

There is nothing illegal with the above code fragment, assuming that your etc... introduces another variant of MYPROTOCOL. Your local (but unused) declaration of INT n, for example, is perfectly legal just above the ALT guard. It could also be located just above (and aligned with) any of the CASE variants if that were useful.

Indentation errors are trivial to correct. Mail me your code and tell me the line number of any indentation errors reported by the compiler and I'll tell you what's wrong. If it's a general point, I'll make up the relevant (anonymous) question and post an answer to these pages.

Keywords: q7 , incorrect-indentation


Question 68:

I've forgotten how to implement the lookup table for the screen positions for the dining philosophers. Any help would be appreciated.

Answer 68:

Your animation code should not be highly repetitive with the same logic repeated with different magic numbers - e.g. for displaying new positions of the different philosophers. Having a table of anchor coordinates for each philosopher may help. A table is simply an array of VALues (i.e. constants). For example:

  VAL [][2]BYTE phil.anchor IS [[40, 5], [70, 10], [55, 15],
                                [35, 15], [10, 10]]:

where the [][2]BYTE could have just been [][]BYTE, but being specific about the dimension of the coordinates (rather than the number of them) seems right. We could have been even more explicit and written [5][2]BYTE, but that seems too much. Any way, the compiler will fill in the sizes of any blanks in what we write after the IS.

With the above, it's nice to give names to the two indices of the [2]BYTE array coordinates - e.g.

  VAL INT X IS 0:
  VAL INT Y IS 1:

Then, if we want to move the screen cursor to the anchor point for philosopher i - and we know that that i is a valid philosopher number (i.e. 0 through 4):

    cursor.x.y (phil.anchor[i][X], phil.anchor[i][Y], screen)

or, more efficiently:

    VAL [2]BYTE phil.i IS phil.anchor[i]:
    cursor.x.y (phil.i[X], phil.i[Y], screen)

since it only checks the array index (for out-of-bounds error) and calculates the address of phil.anchor[i] once.

Keywords: q7 , cursor , table , animation

Referrers: Question 43 (2009) , Question 30 (2008) , Question 84 (2003) , Question 29 (2002)


Question 69:

In a post, Fred says that the maximum negative 32 bit int is -2147483648, so I have coded appropriately ...

  -- ensure seed is positive & legal
  IF
    seed = (-2147483648)       <---------ERROR!!!
      seed := 2147483647
    seed < 0
      seed := -seed
    seed = 0
      seed := 1
    TRUE
      SKIP

But I get an error on the line arrowed above which says:

          Overflow when evaluating constant expresssion

Help!! Have I done something wrong or is the info on cs2 wrong?

Answer 69:

The compiler treats -2147483648 as an expression, so it gets an error when trying to evaluate 2147483648 (which is larger than the largest INT). If it got past that, it would get another error trying to negate it.

occam has a special way of naming the largest and smallest of any of its number types. For example,

  MOSTNEG INT
  MOSTPOS INT

give you, respectively, the most negative and positive integers. Other ways we can write MOSTNEG INT are:

  #80000000
  1 << 31

But ... my colleague, David Wood, suggests you might like to consider:

  TIMER tim:
  INT seed:
  SEQ
    tim ? seed
    seed := (seed >> 2) + 1

Keywords: inverting , int , random , q7

Referrers: Question 29 (2002)


Question 70:

Once the first draft of my q7 program is compiled and run, it produces this error:

    Philosopher 1 is thinking
    KROC: Range error / STOP executed (signal 4)
    KROC: Fatal error code 1, core dumped
    Abort (core dumped)

I don't know what this means, so I would be grateful if you could point me in the right direction ...

Answer 70:

It means your program crashed. There are several possible causes of this run-time error:

I'm afraid the message you report is all you get from the KRoC/Solaris system. If you compile this with KRoC/Linux using the command:

    kroc -d myfile.occ -lcourse

it will tell you the file name and line number of the offending line. [Note: the "-lcourse" flag above is just to link in the course library - something which is automatic with the Solaris version of the kroc command. The active ingredient of the above command is the "-d" flag.]

Keywords: q7 , range-error , stop

Referrers: Question 31 (2012) , Question 6 (2011) , Question 53 (2006) , Question 43 (2004) , Question 30 (2003) , Question 86 (2003) , Question 11 (2002)


Question 71:

When tapping the channels for the philosophers and forks, Fred recommended giving each one an id. If it were Java, I would simply assign each object an individual id when their constructor was called. Can I do something similar in occam?

Answer 71:

Yes. To set up a number, say n, of thing processes and give each instance its own id is easy. First, the PROC header for a thing must take an id parameter - for example:

  PROC thing (VAL INT id, ...)
    ...  body of thing
  :

Then, to set up the instances:

  PAR i = 0 FOR n
    thing (i, ...)

That's all.

Keywords: q7


Question 72:

When I recieve the appropiate case statement, I want to output a string. But what command does that?

Answer 72:

It sounds like you don't know about:

  out.string ("any old string", fieldwidth, screen.channel)

from the course library? Look at any of the examples in your examples directory on raptor - or the answers directory at:

    /usr/local/work/co516/answers/

Keywords: q7


Question 73:

I have the following code:

    VAL INT i.mod.n IS i\n:
    in[i.mod.n] ? CASE
      thinking
        SEQ
          cursor.x.y (1, (i.mod.n * 4) + 5, screen)

which generates an error saying that the operator * has operand of different types. Is 4 not an INT as I assumed it would be? Or is it because i.mod.n is a VAL INT and 4 is a plain INT?

If it is the latter, surely not allowing a VAL INT to be muliplied together by an INT is being rather pedantic - seeing as they are obviously both INTs.

Anyway, as to a solution, is there any reason why i.mod.n is a VAL INT rather than just a plain INT which would allow me to mutiply with it without having to define all my other values as VAL INTs?

Answer 73:

The first two parameters for cursor.x.y are screen coordinates and they are of type BYTE - so BYTEs must be supplied.

The compiler looks for a BYTE as the first parameter and finds a 1 - that'll do! When it looks at the second argument, it finds an expression - an addition of two operands. The result has to be a BYTE which implies that both those operands must be BYTEs. The right operand is 5 - which is fine. The left operand is another expression - a multiplication of two operands. That result must be a BYTE and so, therefore, must be its two operands. Now, the right operand is 4 - which is fine. But the left operand is i.mod.n, which is an INT - not a BYTE. Error!

occam has a very simple rule about binary operators in expressions: both operands must have the same type and the same precision and the result has that same type and precision. There is no automatic casting between types - all casts, if needed, must be explicitly programmed. What-you-see-is-what-you-get.

Your other points about VAL are not relevant. VALs have no impact on types. A named VAL INT has INT type and may be freely added/multiplied/etc. with other INTs (whether VAL INTs or variable INTs). We want i.mod.n to ba a VAL because we don't ever need to change it - declaring it as a VAL will get the compiler to reject any code we might mistakenly write that tries to change its value.

To correct your code, you can't just declare i.mod.n to be a VAL BYTE. This is because it is used to index an array and array indices are always INTs. Instead, cast it at the point in your code where it needs to be a BYTE:

          cursor.x.y (1, ((BYTE i.mod.n) * 4) + 5, screen)

Of course, you have to be sure that evaluation of the above expression will always remain within the legal bounds of a BYTE (which are 0 through 255 inclusive). Hopefully, this will be the case.

Note: the above expression will cause the arithmetic to be performed using BYTE arithmetic. The following code causes INT arithmetic to be used (which on a SPARC or Pentium etc. will be more efficient - although that would not be not the case if we were compiling directly into silicon) and only casts the result into the needed BYTE:

          cursor.x.y (1, BYTE ((i.mod.n * 4) + 5), screen)

Keywords: type-mismatch , cast

Referrers: Question 32 (2012) , Question 89 (2003) , Question 74 (2000)


Question 74:

Is there anyway to cast INTs to BYTEs?

Answer 74:

Yes. See the answers to Question 7 (2000), Question 66 (2000) and Question 73 (2000) - for example.

Keywords: cast

Referrers: Question 89 (2003)


Question 75:

I get a compiler error when I adpated the philosopher's process to accommodate the sending of data when the philosopher does an action. It says that within a PAR scope, I cannot output to the same report channel (to the display process) in parallel branches of the PAR. Which is fair enough. But how can I get past this?

Answer 75:

One way is to put in two report channels from the philosopher and, then, either a separate multiplexor process that merges those two down to one or just take both report channels to the display process (which will get a bigger array of input channels to service).

Better, though, is to get your fork processes to have report channels to the display. Then, don't bother reporting fork acquisitions from the philosopher (which is, I guess is what you were trying to do in parallel - because the fork acquisitions occur in parallel). The forks can report where they are directly on their own report channels.

Keywords: q7 , parallel-output


Question 76:

I think we've already been told, but where are we meant to find the documentation on all the methods we need for the display process, in order to move the cursor around the screen etc?

Answer 76:

Yes - you have been told! See, on raptor, files:

    /usr/local/work/co516/libsrc/utils.doc

which is a text file (not an MS-Word document!). The procedures you want are documented at the end of the file, following the comment (fold) line:

    ...  screen stuff (VT220 protocol)

Alternatively, you could browse the full source code:

    /usr/local/work/co516/libsrc/utils.occ

There's also a simple demo of the cursor.x.y procedure in:

    /usr/local/work/co516/examples/test_utils.occ

Keywords: q7 , display

Referrers: Question 77 (2000) , Question 78 (2000)


Question 77:

Ok, I am confused. What's the deal with all the seed things? Also what's the deal with the animation? Where can I find some examples of some coding for screen display?

[I'm combining this question with the following one (PHW)]

Please could you tell me how to generate a random number in occam? I've forgotten and can't find it in the notes. Thanks.

Answer 77:

All these things have been explained in your seminar groups. I'll just point you at Question 76 (2000) for information about implementing the screen display and:

    /usr/local/work/co516/libsrc/random.occ

for information about the random number generating FUNCTION, for which you need to set up and maintain a seed variable.

Keywords: random , q7

Referrers: Question 21 (2001)


Question 78:

Does anyone know the pages in the course notes or on the web which give examples of graphic representation in occam?

Answer 78:

How to do the graphic animations (textual only) has been explained in your seminar groups. There is nothing in the course notes or the web. There is not much to say! You just need to know how to place the text cursor anywhere on the screen and output text. See the answer to Question 76 (2000) for the basics.

Keywords: display


Question 79:

When it comes to TIMERs, how is the time counted? Does the internal enviornment time in nanoseconds or microseconds? Also does it go like this:

  1000000 nanoseconds = 1 second
  10000 microseconds = 1 second

Answer 79:

occam TIMERs, in KRoC Solaris/Linux systems, increment every microsecond. And, for information:

  1000000000 nanoseconds = 1 second
  1000000 microseconds = 1 second

Keywords: timers


Question 80:

The question says:

"Thinking and eating by the philosphers should be modelled by random (but finite!) delays."

Assuming we have obtained a random number, what's the best way to implement the delay ... i.e. pause execution for a random time? Is there a wait(time) function or such like?

Answer 80:

See slide 4-40 and sections 3.4/3.5 of the "OCCAM2 CHECKLIST" paper. Spelling it out:

  TIMER tim:
  INT t:
  SEQ
    tim ? t
    tim ? AFTER t PLUS waiting.time

Keywords: q7 , timers

Referrers: Question 59 (2004)

Valid CSS!

Valid XHTML 1.0!

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
Last modified Mon May 20 13:50:24 2013
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.