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.
Do we need to use occam that is going to work on raptor or can we make use of the additions in the KRoC/Linux version. For example I'm considering using the STEP stride part for the replicator.
Next when using replicators, why can't I pass "i" into the "cursor.x.y()" PROC in this code ?
PAR i = 8 FOR 5 STEP 2 SEQ cursor.x.y (23, i, out) -- print stuff
Where "i" is the line number. The error is a type mismatch for parameter 2 in "cursor.x.y()". Surely "i" is an integer and should be accepted ?
Any help appreciated...
For KRoC/Linux extensions (rather, occam-pi extensions), yes, using those is fine. We'll most likely be testing your code on such a machine.
The reason you can't pass "i" as a parameter is because "cursor.x.y" takes "VAL BYTE" parameters (not "VAL INT"). The solution for such things is to cast the parameter to the appropriate type:
cursor.x.y (23, BYTE i, out)
Given the code you've got above, it should generate another error also (related to parallel usage), but that should be slightly more obvious.
Is it possible to specify more than one condition in an "IF" process ? For example:
IF x = 0 AND y = 0 -- do something
If so which operators should be used ? When I compile something similar to the above I get an error saying:
Expected new line, found AND
This error occurs because you need explicit bracketing (occam has no operator precedence), even though the alternatives don't make much sense in this case. The correct way to write that would be:
IF (x = 0) AND (y = 0) -- do something
How do I output the value of "n.sat.down" to the screen ? Is the only way to add an "out" channel the PROC header and do an "out.int" on it ?
If "n.sat.down" is a tag in a variant protocol, it doesn't have any meaningful value. Some meaningful data might be communicated as part of the protocol, however. You mention adding an "out" channel, but to what PROC in particular ?
To avoid complication, the correct place to handle the output of this information is in your "display" process. Wiring it up to the "security" process (by default the only process that knows how many philosophers are sat down) should be fairly straight-forward.
I have a quick question relating to my 'animation' - could you give any tips/ideas for nice(r) way of making the philosophers move about the screen without hard coding in the locations of every movement?
In my more 'advanced' animation (which has been a challenge to say the least) I have had a lot of hassle using a hard coded method. The code just to move a philosopher to the table (and it's currently not very smooth) is around 300 lines. Ouch.
I am sure there is a better way of doing things but I have racked my brains and I can't think of anything :(. The only other idea was to create a "large" VAL [][5][2]BYTE array that stored all the locations, and for each movement the required value is pulled out the array. That doesn't seem much nicer though; occam doesn't seem to allow you to span this sort of thing over multiple lines either.
Any sort of help would be greatly appreciated, however small!
If ever you find yourself writing long sequences of repetitive code, where the differences are primarily in number values, you are doing something wrong, ugly and inefficient! So, your 300 lines of code is not a good idea.
Your 'better way' is much better, although it can be improved (see towards the end of this answer). Your VAL [][5][2]BYTE is, presumably, a 2-dimensional array of coordinates (i.e. [2]BYTEs), with the [5] index being for the philosophers and the unsized outermost dimension (i.e. []) being for the number of coordinates (i.e. the length of the path). That might make slightly more sense (and convenience for programming) with the two outer dimensions swapped around -- i.e. VAL [5][][2]BYTE.
occam does allow long lines to be broken across multiple lines ... but maybe I never told you! You can break a long line after commas, operators and the keyword IS. For example, the very long one-line declaration:
VAL [n.phils][][2]BYTE path IS [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]], [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]], [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]], [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]], [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:
can be much more readibly laid out:
VAL [n.phils][][2]BYTE path IS [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]], [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]], [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]], [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]], [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:
The rule about indentation for continuation lines is that any indentation at least as great as the initial line is allowed. So, the following, rather stupid, layout is also possible:
VAL [n.phils][][2]BYTE path IS [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]], [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]], [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]], [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]], [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:
but we wouldn't, of course, ever do that! Another use of breaking lines after commas we have seen lots of times -- in PROC headers with long parameter lists:
PROC thing (CHAN OF INT in0, in1, CHAN OF BYTE keyboard, screen, error, VAL INT id, interval, [][]REAL64 data)
instead of:
PROC thing (CHAN OF INT in0, in1, CHAN OF BYTE keyboard, screen, error, VAL INT id, interval, [][]REAL64 data)
Breaking lines after operators helps keep large expressions neat -- for example:
first := (first - second) + ( ((-first) + (third - second)) * (rotational.torque - (ratio/2)) )
could be written:
first := (first - second) + ( ((-first) + (third - second)) * (rotational.torque - (ratio/2)) )
which might help a little.
Getting back to improving your path description for a wandering philosopher ... rather than declare a table of absolute coordinates for each path position, consider a table of relative movements. For example:
VAL [n.phils][][2]BYTE path IS [[[left, 3], [up, 5], [right, 2], [up, 4], [left, 1], [down, 2]], [[down, 8], [up, 3], [left, 6], [down, 1], [left, 6], [down, 3]], [[right, 3], [down, 2], [right, 8], [down, 9], [right, 1], [down, 5]], [[up, 5], [left, 5], [down, 2], [up, 2], [down, 1], [up, 3]], [[up, 9], [right, 9], [up, 2], [left, 2], [up, 3], [left, 6]]]:
where your movement code interprets [left, 3] as "move left 3 places" etc. Predeclared, of course, would need to be something like:
VAL BYTE left IS 0: VAL BYTE right IS 1: VAL BYTE up IS 2: VAL BYTE down IS 3:
Elsewhere would be needed a table of absolute start coordinates for each path movement.
That just leaves the problem that all the above path lengths have to be the same length? With the modern occam-pi language, that's not a problem ... we can use dynamically sized mobile arrays. For classical occam, you could pad out short paths with some dummy movement elements - e.g. STAY where:
VAL BYTE stay IS 255: VAL [2]BYTE STAY IS [stay, 0]: VAL [n.phils][][2]BYTE path IS [[[left, 3], [up, 5], [right, 2], [up, 4], STAY, STAY], [[down, 8], [up, 3], [left, 6], [down, 1], [left, 6], STAY], [[right, 3], [down, 2], [right, 8], [down, 9], [right, 1], [down, 5]], [[up, 5], [left, 5], STAY, STAY, STAY, STAY], [[up, 9], [right, 9], [up, 2], [left, 2], [up, 3], STAY]]:
Keywords: q7 , animation , long-lines
Referrers: Question 43 (2009) , Question 30 (2008)
Just out of curiosity, which chapter will we be examined on ? Will we be expected to know about the Transputer and the different processes (talked about in chapter 2) ?
You will be examined on the material presented in the lectures. For the occam part of this module, we omitted chapter 1, (most of) chapter 3, chapter 7 and chapter 9. That leaves chapters 2, 4, 5, 6, 8, 10 and some of 3 (chapter 3 has little technical content). But the papers in the course notes are also part of the examinable material. The "Checklist", "occam Approach", "Hard Real-Time" and "GOTO" papers all write up material presented through the slides. The "Emulating", "Graceful" and "Paradigms" papers explore ideas we didn't present, but a study of them will broaden your understanding and confidence. [BTW, the Transputer was not mentioned in chapter 2 and, no, you will not be examined on the Transputer!]
For the rest of this term, we will be studying concurrency in Java through the JCSP packages, which provide the same model you have learnt through occam. The JCSP materials are also, of course, examinable.
All this will be apparent to those attending lectures. If you miss any, it is your responsibility to find out what you missed ...
Keywords: exams
Referrers: Question 129 (2004)
Could you explain "SHARED" channels again and maybe give an example ? From the class they seem like a cleaver idea but now when it comes to coding them I am a little lost.
[Note: the first part of this answer is now obsolete! The SEMAPHORE data type is no longer supported by the multicore run-time systems for occam-pi. The second part of this answer (using SHARED channel) is the correct way to do things now.]
There are two ways to do shared-channels in occam, and which one you choose will depend on whether you're coding on Linux or Solaris.
KRoC/Linux has built-in support for shared channels, called "anonymous channel types" in the form most useful for Q7. You can find a fairly terse example of these here.
Shared channels on the KRoC installed on raptor must be done manually -- by turning off compiler usage-checks and using "SEMAPHORE"s to provide mutual exclusion.
For comparison and reference, below are two equivalent versions of a simple test program that use shared channels:
#INCLUDE "semaphore.inc" -- NOTE: this version is no longer valid. #USE "course.module" PROC hello (SEMAPHORE sem, CHAN BYTE out!, VAL INT id) SEQ claim.semaphore (sem) --{{{ output stuff out.string ("hello world from ", 0, out!) out.int (id, 0, out!) out.string ("*n", 0, out!) --}}} release.semaphore (sem) : PROC main (CHAN BYTE kyb, scr!, err!) #PRAGMA SHARED scr SEMAPHORE sem: #PRAGMA SHARED sem SEQ initialise.semaphore (sem, 1) PAR i = 0 FOR 10 hello (sem, scr!, i) :
and (if using KRoC):
#USE "course.module" PROC hello (SHARED CHAN BYTE out!, VAL INT id) CLAIM out! SEQ --{{{ output stuff out.string ("hello world from ", 0, out!) out.int (id, 0, out!) out.string ("*n", 0, out!) --}}} : PROC main (SHARED CHAN BYTE scr!) PAR i = 0 FOR 10 hello (scr!, i) :
but (if using the Transterpreter – see Question 22 (2008)):
#USE "course.lib" PROC hello (SHARED CHAN BYTE out!, VAL INT id) CLAIM out! SEQ --{{{ output stuff out.string ("hello world from ", 0, out!) out.int (id, 0, out!) out.string ("*n", 0, out!) --}}} : PROC main (CHAN BYTE key?, scr!, err!) SHARED ! CHAN BYTE screen: -- output end shared PAR PAR i = 0 FOR 10 hello (screen!, i) WHILE TRUE -- byte "id" process BYTE ch: SEQ screen ? ch scr ! ch :
Keywords: q7 , shared-channel
This is used for the animation:
SEQ clear.states (4 + (4 * n), out) ...
but when I try to use "clear.states" I get an error! help.
Saying what error you get might be useful.. But "clear.states" must be something you've defined yourself -- it's not provided by any library. The errors generated by the compiler are generally meaningful and useful, and should be telling you what the problem is.
Keywords: q7
I'm thinking of changing my protocol from:
PROTOCOL REPORT CASE thinking hungry ... :
to:
PROTOCOL REPORT CASE thinking; INT hungry: INT ... :
to tell me which philisopher is hungry, thinking, etc. Is this a wise move or is there another way I can find this out in the "display" process ? Currently I'm ALTing over the channels to see if they're thinking, hungry, etc.
Currently if a philisopher is thinking it prints (philosopher is thinking) with no knowledge of who is thinking.
Yes, this probably is a wise move. The only other way you can get that information is by having the "display" process knowledgeable about its wiring. I.e., in the array of "REPORT" channels, which channel is connected to which philosopher, etc. This is not entirely desirable, however, since re-wiring such a network would break the "display" process.
How many more channels need to be added to the PROC header of the philosopher? When I add an output channel to my "fork", "philosopher" and "security" PROCs, I get an error in the "secure.college" PROC stating parallel outputs on one channel. How do I get around this?
Form the code from the diagram of it -- you'll see that there is only one additional (report) channel coming out of a philosopher, so that's all that should be added to its header. The error relating to parallel output is in "secure.college", so that is where the error lies -- not in "philosopher", etc. A key rule is you can't do parallel outputs to the same channel. So, we need an array of channels, one for each of the reporting processes inside "secure.college". The "display" process takes the other (reading) end of that array of channels. How to do this has been covered fairly extensively in the seminars. If you're already using an array of channels, check the indices you're using -- one or more must be wrong if the compiler is giving you this error (you can expand the replicators by hand to see where the error lies).
Keywords: q7
Is this the correct piece of code for waiting a random time ?
SEQ seed := seed + id i, seed := random(num, seed) tim ? t tim ? AFTER t PLUS i
More or less, yes. Make sure you initialise "seed" appropriately though -- the code above initialises it based on itself (if undefined, it'll stay undefined). As covered in the seminars, a quick way to get an initial seed value is:
tim ? seed seed := (seed >> 2) + 1 -- maybe also add in the `id'
Remember also that your seed should be explicitly initialised like this just once -- before loop entry. Within the loop, cycling through the philosopher's life, the seed value gets updated as you use the random function. The sequence of seed values takes you through the "random" numbers. If you re-initialise the seed every time round the loop, the computed randomness will be lost.
Is it possible we can actually see the implementation of the PROCs, like: "erase.screen()", "erase.bol()" and others in the utils file ?
Yes, just look at the source code! See Question 63 (2003) for an indication of where it is.
Keywords: q7 , course-library
Why is this bit of code gvining the error: Parallel outputs on channel out, when the channels down and up are used in security as well as philosopher?
[Code snipped]
As said many times before, we can't debug specific code on these pages!
However, the compiler is generating a correct error message - it usually does. Your network has mutliple processes writing to the same out channels - the up and down channels are irrelevant here.. When you've fixed that, you might want to put those out channels in the parameter list for secure.college - having them as local channels mean they don't connect to anything in the world outside the college ... such as a display process ...
Keywords: q7
Hello. I saw your answer to Question 109 (2003) about the colours in text and was wondering where and how to find out the codes for other colours. Thanks.
Well, the answer to the question you referenced says to do a quick Google search. I just did and it came up with this link which, when combined with Question 109 (2003), tells all, :).
Keywords: q7
How do we submit our dining philosopher's assignment?
Copying from the newsgroup announcement ...
Your assessment, "A4 DINING PHILOSOPHERS ANIMATION", is due on Monday in week 18 - i.e. Monday, 14th. February, 2005.
This time, we want to compile and run your programs! Submission directories are open at:
\\raptor\files\proj\co516\q7\(from Windows)
or:
/usr/local/proj/co516/q7/(from Unix/raptor)
Please copy your source code (.occ) file(s) there. Please do *NOT* copy executables. You only have access to <your-login-name> directory.
If your solution follows the standard model (i.e. an array of channels connecting the college process and the display process, with the display also connected to the screen channel), you do *NOT* need to include a network diagram.
If your solution has a non-standard network, please include a network diagram with your submission. This can be as a .pdf, .ps, .ppt or .doc file. For anything else, you must submit hard copy to CAS reception together with a cover sheet. A neat hand-drawn diagram is very acceptable through that route.
The submission directories will close at midnight between Monday/Tuesday - i.e. at 00:00 on Tuesday, 15th. February.
Keywords: q7
When I try to run my q7 answer on my Linux box (Mandrake 10.1) I get this error:
KRoC: unable to find clock file (.kroc_clock or /etc/kroc_clock)
What does it mean and what can i do to fix it ?
It's because you're missing the KRoC clock file. When you installed the software it prints out a message saying that you must copy "~/.kroc_clock" to the current-directory or to "/etc/". This file just contains your CPU speed in MHz (as read from "/proc/cpuinfo"). Newer versions of KRoC/Linux (1.3.4-pre4 and above I think) will automatically read the speed out of "/proc/cpuinfo" if a clock file isn't found.
Is A7 the minimum you expect from us for Q7 ?
It's minimal in the sense that if you implement something that produces similar output you can get 100%. But that's a generous estimate; some marks are inevitably lost for untidy coding, errors, etc.
Keywords: q7
Hi there, can you give some clues of how to get the forks working in Q7. Everything I am trying isn't working :-(
The forks already work by default -- adding the reports shouldn't break them! The best idea would be to mail your seminar leader with a copy of the code, who can then advise on what the problem is.
Keywords: q7
Do you think anyone would be offended if someone were to name their philosophers after occam seminar leaders ;)
No ...
Keywords: q7
Oh dear oh dear - q7-bodden-2003: it just crashed on me after running for a while! Shocking.
KROC: Fatal error / STOP executed (signal 4) KROC: Fatal error code 1, core dumped Abort
Aren't these supposed to be 'model' answers? ^_^
Humm ... I guess you mean the a7-bodden-2003 program ... there isn't a q7-bodden-2003 one?!! [Actually, it's simple naming typos like these that cause masses of software crashes, :(]
But, seriously, a7 is the model demo executable. All others are to give you ideas/challenges. We haven't verified them completely. Thanks for telling us that that one breaks. We will fix ...
Keywords: q7
In occam, if I've got a BYTE array, I would have thought I could do something like this: (where "i" is an INT)
array[5] := BYTE i
but it doesn't appear to work, can you explain why that is, when something such as this works perfectly fine: (where "b" is a BYTE).
array[5] := b
That should work fine, and does for me.. What error (exactly) are you getting ? Something else must be wrong..
Referrers: Question 121 (2004)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License. |