Jump to content
IGNORED

Concurrent processes in Pascal


Rossman

Recommended Posts

Anything worth engineering is worth over-engineering! Er, no, I am pretty sure that is not correct. Difficult to debug... difficult to maintain... Hmmm.

 

Well, ok, maybe not. But over-engineering is a lot of fun!

 

Just for sake of researching it - and because I was not looking forward to refactoring my game logic - I decided to investigate how I could reduce the delay created at startup by shuffling 4 decks at game start. So I created a little model program of concurrent processes. One process fills an array (as fast as it can, up to 2,000 values). The other process reads from the array (no more than 6 values at a time). Essentially, I seed the array with 6 values and then go concurrent. I believe I need to implement a semaphore so the second process does not read ahead of the first process writing.

 

So that I would know that Things Are Happening in my concurrent processes, it seemed to me that I could create a little visual cue that each process was stepping through. I did this:

 

program contest;
type
valstack = array[0..1999] of integer;
sixcards = array[0..5] of integer;
var
valyoos : valstack;
onehand, showhand : semaphore;
cards : sixcards;
mainpoint : integer;
process defvalyoo;
var
x : integer;
sc : char;
begin
...
while x <= 1999 do begin
wait(onehand);
valyoos[x] := x;
x := x + 1;
gotoxy(12,12);
write(sc);
if (sc = '-') then
sc := '|'
else
sc := '-';
signal(showhand);
end;
end;
process gethand;
var
t, y : integer;
cardo : array[0..5] of integer;
tc : char;
begin
...
while t < 4 do begin
y := 0;
while y <= 5 do begin
wait(showhand);
cardo[y] := valyoos[mainpoint];
y := y + 1;
mainpoint := mainpoint + 1;
signal(onehand);
end;
y := 0;
while y <= 5 do begin
wait(showhand);
y := y + 1;
gotoxy(15,12);
write(tc);
if (tc = '*') then
tc := '-'
else
tc = '*';
signal(onehand);
end;
end;
begin
seminit(onehand,0);
seminit(showhand,1);
start(defvalyoo);
start(gethand);
...
end.
And this worked. Well, it worked as far as the limits of the nested loops in showhand. I failed to work out the fact that the consume-the-array (gethand) process would expire and therefore prevent the fill the array process (defvalyoo) from fulfilling its potential (of 2,000 array updates) by way of semaphore. But, my little concurrent experiment worked. I have little spinners going a few characters apart in row 12, simultaneously. It's kinda cool.
But...
If I try to write out the value of an integer or array variable within a process, I get a stack overflow error.
For example, In gethand, instead of doing the write(tc) and if logic that follows, if I have
write('Card: ', cardo[y]);
or
write('Card: ', y);
I get a stack overflow error at runtime on the first write attempt. I get Card: **STACK OVERFLOW** at runtime. And then I have to do an unhappy warm restart.
What seems interesting to me is that I can WRITE (as a verb) by proxy. The variable tc type char, who's state is derived from a previous state of itself. It spins, which indicates the code logic appears to be stepping through. The spinners run in fits and starts as I would expect, side-by-side.
But I cannot write a variable value that is an integer or an array value. It doesn't matter whether it is a local (cardo[y], or y) or global (valyoos[mainpoint-1], or mainpoint). I get a **STACK OVERFLOW** at runtime.
This could be (and likely is) a monumentally stupid error on my part (it would not be the first time). But it seems odd to me that I can write by proxy, but not by value. The logic is executing and not failing. But it feels a bit like Heisenberg's uncertainty principle applied..
Concurrency isn't essential to my little program, but it might expedite startup. And, to make this practical, I will have to make my game logic process along side the card logic and, possibly, along side the wagering logic (not yet implemented).
It is over-engineering. But it is also lots of fun to experiment with. Anybody run into this themselves?
  • Like 1
Link to comment
Share on other sites

I have not used the Pascal system on TI but I am wondering if the documentation explains stack usage per process?

 

Could it be that the stack size is set somewhere at start up and its a shared stack space that gets consumed in chunks by each process? This might leave your print code with nothing left to format a number to text.

 

Full on conjecture here.

Link to comment
Share on other sites

In UCSD Pascal, each process has its own stack space. By default, it's 200 words. This may not be enough to hold local variables and the activation record of the system calls to the write procedure, including that procedure's local data.

Try increasing the stack space to, say, 400 words and see if it makes a difference. You do that by adding parameters to the start statement.

var
  pid: processid;

process myprocess;

begin
....
writeln(something);
...
end;


begin
.....
start(myprocess, pid, 400);
...
end.

Processid is a predeclared type. It's used here only because the stack size is the third parameter to the start command, so you have to fill it out with getting a process id you don't need. Unless you want to start messing with the internals of the concurrency support.

Edited by apersson850
Link to comment
Share on other sites

In UCSD Pascal, each process has its own stack space. By default, it's 200 words. This may not be enough to hold local variables and the activation record of the system calls to the write procedure, including that procedure's local data.

Try increasing the stack space to, say, 400 words and see if it makes a difference. You do that by adding parameters to the start statement.

 

Could it be that the stack size is set somewhere at start up and its a shared stack space that gets consumed in chunks by each process? This might leave your print code with nothing left to format a number to text.

 

 

 

Thanks to both of you for the suggestions. I have not followed-up yet. Investigating concurrency gave me the luxury of putting off an unpleasant refactoring of my core game logic! I bit the bullet and got on with refactoring. I'm about half-way through it, and it is going well. The code is better organized, and more read-able, and better encapsulated. Have one major unwind yet to go.

 

I will revisit my concurrency experiment during the week and let you know how it turns out. For what it's worth, I was pleasantly surprised with how far I was able to push my concurrency experiment.

 

Again, thank you for the tip. I hadn't thought about the stack size.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...