Page 1 of 2

Bail out from parent procedure

Posted: Thu Mar 15, 2007 6:25 pm
by Trond
Basically I want to create a program that is constantly running (like the PB compiler). It can then accept data and process it.

If the data has errors, the program will probably be in some deeply nested procedure when it finds the error. The program should then then stop the processing, but continue running and waiting for other data.

What is the best way to handle this, and return to a clean main loop after an error?

Posted: Thu Mar 15, 2007 6:43 pm
by thefool
Absolutely simplest way is to do a restart.

Another solution i use myself: Have the place you are nested in check for a
global "quit" variable. If its 1, exit the loop. The quit variable can be checked from many places, or simply written directly in the process, which is quite easy and safe.

Posted: Thu Mar 15, 2007 7:06 pm
by Trond
If I restart, I have to reload static data.
If I use a global error variable, I have to check this in A LOT of places.

Posted: Thu Mar 15, 2007 7:15 pm
by Kaeru Gaman
the problem is:
if you want to jump out, you at least have to know how deep in sublevels the code is,
because you'll have to POP every backjump-data from the Stack to continue with the mainloop.
so you would have to keep trace of the nesting-level.

the global "quit" is a practicable solution.

also it would be possible to give ALL(!) of your procedures the possibility to return an error-code,
wich will cause also the parent-proc to return-with-error immediately.

in every case you'll have to integrate it completely into your concept,
it is nothing to implement later easily....

Posted: Thu Mar 15, 2007 7:50 pm
by srod
You could of course place the processing within a thread and use WaitThread() in the main code etc. Then again, not much point in a thread if the main code is then stuck waiting I guess. Just an idea!

Posted: Thu Mar 15, 2007 7:58 pm
by thefool
srod wrote:You could of course place the processing within a thread and use WaitThread() in the main code etc. Then again, not much point in a thread if the main code is then stuck waiting I guess. Just an idea!
This is exactly what he wants to avoid :)

I think the global quit-check is the safest solution. If you have a lot of nested loops, just check in the larger ones. if you have eg:

For i=1 to totalLines
for a = 1 to totalLines
;do your stuff
next a
;Check here
next i

Still a lot of checks.

Posted: Thu Mar 15, 2007 8:00 pm
by Trond
There should be a built-in feature for this in modern programming languages. That would be really cool.

Posted: Thu Mar 15, 2007 8:03 pm
by Kaeru Gaman
This is exactly what he wants to avoid
really?

I think it's a good approach...

the complete processing can be within a thread that will be terminated if an error occurs,
so the level of nesting is no longer a problem and the main-thread isn't touched at all....

Posted: Thu Mar 15, 2007 8:03 pm
by thefool
Trond wrote:There should be a built-in feature for this in modern programming languages. That would be really cool.
Its so easy to make one using BREAK.
'Why would the other method be better?

Posted: Thu Mar 15, 2007 8:04 pm
by thefool
Kaeru Gaman wrote: the complete processing can be within a thread that will be terminated if an error occurs
And you call this SAFE?
besides he said to use WAIT THREAD. wait thread waits till a thread stops, no point except you get more overhead usign a THREAD. THINK!

Posted: Thu Mar 15, 2007 8:05 pm
by srod
What's unsafe about it? Providing you don't use KillThread() and just use ProcedureReturn etc,

Posted: Thu Mar 15, 2007 8:17 pm
by thefool
srod wrote:What's unsafe about it? Providing you don't use KillThread() and just use ProcedureReturn etc,
Because he don't want to wait for the processing to finish. Nothing unsafe, but then there is no point in it!

Posted: Thu Mar 15, 2007 8:32 pm
by srod
Yea, I agree on that score - it was just something to throw into the pot! I guess we need to know a little more about the structure of the procedure before being able to really comment.

Then again I guess the structure of the procedure is exactly what Trond is asking about. Personally, I farm every step of the data processing out to a separate function, which is only called if the preceeding one does not flag an error rather than try and nest it within one big procedure. But that is just personal preference. I find it leads to some easily maintainable code etc.

Posted: Thu Mar 15, 2007 9:12 pm
by thefool
srod wrote: Then again I guess the structure of the procedure is exactly what Trond is asking about. Personally, I farm every step of the data processing out to a separate function, which is only called if the preceeding one does not flag an error rather than try and nest it within one big procedure. But that is just personal preference. I find it leads to some easily maintainable code etc.
Yeah i tend to split it apart too. And then have one procedure to hold the loop which call the others. But it still leads to the same question, how do he test when to stop! I think the only real solution is the quit variable. Then he need to place it at the right spot

Posted: Thu Mar 15, 2007 9:53 pm
by Trond

Code: Select all

For i=1 to totalLines 
for a = 1 to totalLines 
;do your stuff 
next a 
;Check here 
next i
That's a working way to do it, but the problem is that this is not a simple loop, it's a huge program. So inside "do your stuff" there will be tons of other loops and procedure calls.
With the global error variable, if I have a procedure which is called from a lot of places, and should stop the process if it fails, I would have to check it after every call, instead of processing the failure inside the function.
You could of course place the processing within a thread and use WaitThread() in the main code etc. Then again, not much point in a thread if the main code is then stuck waiting I guess. Just an idea!
Even if I place the code in a thread, how to I stop in the middle of the thread?
the complete processing can be within a thread that will be terminated if an error occurs,
so the level of nesting is no longer a problem and the main-thread isn't touched at all....
I will have to allocate a lot of memory, which will be flushed down the toilet when I use KillThread().
What's unsafe about it? Providing you don't use KillThread() and just use ProcedureReturn etc,
If I only use ProcedureReturn there's no extra benefit in using a thread.

thefool wrote:
Trond wrote:There should be a built-in feature for this in modern programming languages. That would be really cool.
Its so easy to make one using BREAK.
'Why would the other method be better?
This is the current way of doing it:

Code: Select all

Global Current.c
Global ErrorOccured = 0

Procedure GetChar()
  If Eof(0)
    ErrorOccured = 1
  EndIf
  Current = ReadCharacter(0)
EndProcedure

; Call
GetChar()
If ErrorOccured
  ProcedureReturn
EndIf
That really isn't funny any more when you call GetChar() from 40 different places inside your program. And to do this for every function that can fail will make the code be more error handling than actual code. Especially, since every function that uses a function that can fail now can fail as well.

Compare to build-in handling(pseudocode):

Code: Select all

Global Current.c
Global ErrorOccured = 0

Procedure GetChar()
  If Eof(0)
    BailTo(MainLoop)
  EndIf
  Current = ReadCharacter(0)
EndProcedure

Procedure MainLoop()
  ; Waiting for orders
EndProcedure

; Call
GetChar()
Then again I guess the structure of the procedure is exactly what Trond is asking about.
Yes!
Personally, I farm every step of the data processing out to a separate function, which is only called if the preceeding one does not flag an error rather than try and nest it within one big procedure. But that is just personal preference. I find it leads to some easily maintainable code etc.
That's what I do as well, and I find it leads to 3 lines of error checking for every 1 line of program logic. Which is sort of boring.