Saturday, 27 April 2013

Yet another attempt at try/finally/except

Combined with setjmp/longjmp I previously tried to use a switch statement to hold the try/finally branches of code after noting the similarity between the C# except clauses and a switch/case statement.

I then rather too hastily abandoned this attempt under the impression that the curly braces are an essential part of the switch statement merely because that's how everyone shows them.

As I read further macro tricks I came across the blog of Jens Gusted, author of the unfortunately QT licensed P99 macro set which provides excellent capabilities, including try, catch and except in the syntax form I was seeking which does not involve trailing macros.

So I took a look at how Jens managed it and noticed a few tricks, including use of for (type var=...;...;...) as a way to start an indefinitely chainable single-statement scope that did not need a close-curly-brace but could declare a variable for that scope. But what most caught my eye was his use of the switch statement without curly braces.

It soon became apparent that the switch statement is just a statement, and that the case clauses are merely goto-label placeholders. Curly braces are normally used in switch to form multiple statements into a compound statement.

So if I can express my try and finally/except blocks without the need for me to provide curly braces, there will be no need for me to supply a close-brace.

An examples of brace-less switch statement:
http://stackoverflow.com/questions/8118009/is-there-a-useful-case-using-a-switch-statement-without-braces


switch (x)
    default:
    if (prime(x))
        case 2: case 3: case 5: case 7:
            process_prime(x);
    else
        case 4: case 6: case 8: case 9: case 10:
            process_composite(x);

and blessed day, as Johan Bezem shows further on that page, it allows you to start part-way through a loop, avoiding the continuation test on entry - that is useful!

uint8_t counter;
/* counter will get its value here somewhere */
switch (counter)
    default:
        while (0 < counter)
        {
            case 0:
                /* Perform action */
                counter--;
        }

Also, some people prefer switch(0) default: ... instead of do { ... } while(0) but Jens prefers if (1) { ... } else (void(0))

Try Again

So I repeat my switch based attempt, the parts in bold are provided by the macros:


for(jmp_buf active_jmp_buf; ...; ...)
  switch ((errno=setjmp(active_jmp_buf))) 
  if (0) {
  case 0: // first time around
       {
         ...
         ... throw(123);
         ...
       }
  break; } else default: // break not needed for finally
       {
         ...
       } 

Note that the if/else is bogus, merely a trick to hold two statements without using curly braces to denote a compound statement; although I took care to make it if (0) in order to get legitimate fall-through from the try branch into the finally branch.

I need to finish the for loop so that it only loops once, and perhaps include an extra single-case switch statement within each branch so that misplaced break directives will not affect our exception handling switch statement.

I also wonder if I can have multiple catch clauses like the C# except clauses or if I embed those within a single except clause with an explicit switch statement based on errno.



Friday, 26 April 2013

Another attempt at try/except/finally in C

Since previous work on C cleanup functions I've been trying various means to implement try/finally in C using macros that allow a natural in-code expression of a typical form, like:

try {
  ...
  ... throw(123);
  ...
} finally or except {
  ...
}

It was not possible to use cleanup functions to implement the finally block for many reasons including difficulty of syntax construction, but ultimately because a cleanup function must return normally and so cannot chain an exception:
 It is undefined what happens if cleanup_function does not return normally. http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html 
(Or can they? as I proceed with setjmp I think they can exit with longjmp but at the cost of missing out other cleanup handlers, so maybe I just contradicted myself there.)

I was reading about call-with-current-continuation for C and was re-reminded about setjmp/longjmp and wondered if these might work. (For GENSYM see my previous post).

jmp_buf GENSY(jmp_buf);
if((errno=setjmp(GENSYM(jmp_buf)))==0) {
  ...
  ... longjmp(????, 123);
  ...

} nothing or else { // nothing for finally, and else for except
...
}

the main advantage with setjmp/longjmp is the effective go-back-to consequence of longjmp which avoids the need to recall the names of any generated reference further on in the code. The main difficulty with throw is knowing the reference ???? to use in the longjmp. It should be the most recent active jump_buf --- but how to tell which it is?

We could have a local variable in the try scope which stores the address of the most recent jmp_buf, or in other words we don't need GENSYM macro after all so long as we start a new scope:

{ jmp_buf active_jmp_buf;
if ((errno=setjmp(active_jmp_buf))==0) {
  ...
  ... throw(123);
  ...
} } nothing or else {
  ...
}

which could be generated by these

#define try { jmp_buf active_jmp_buf; \
              if ((errno=setjmp(active_jmp_buf))==0)
#define finally }
#define except } else
#define throw(thrown) longjmp(active_jmp_buf, thrown)

Note how the exception number is smuggled into the exception handler through use of errno.

After looking at some exception handler examples for C# and seeing how much like a switch statement it appeared, I decided I wanted to be able to separate exception types with their own handler and realised that a case statement might do for this:

{ jmp_buf active_jmp_buf;
  switch (setjmp(active_jmp_buf)) {
  case 0:
       {
          ...
          ... throw(123);
          ...
       }
       ...
  case 123:
       {
         ...
       } 
  }
}

Which, though incomplete (consider the lack of break statements) might be generated by something like this:

#define try { jmp_buf active_jmp_buf; \
  switch (setjmp(active_jmp_buf)) { \
  case 0:
#define finally }
#define except(exception) case exception:
#define throw(thrown) longjmp(active_jmp_buf, thrown)

and so expressed like this:

try {
  ...
  ... throw(123);
  ...
} except(123) {
  ...
} except(default) {
  ...
}

Except that we don't have enough close-braces to close the switch statement or the scope containing the jmp_buf which now contains the entire switch statement. This is the sort of problem that plagued previous attempts based on cleanup functions.

With the last new keyword being the finally or the except, any special scopes must be constrained to the try keyword that finally or except can clean them up. Therefore the switch statement is off limits as it requires an extra close-brace, although Francesco Nidito was not too proud to introduce ETRY to solve this problem with his C exceptions (along with Duff's device).

Friday, 19 April 2013

Big heap o' stack frames

Why can't stack frames be allocated on the heap?

Of course I don't mean the heap, I want a stack frame to grow dynamically as much as anyone else, so a fresh memory map region might need allocating for each function cough; but of course dear reader you really want to know why.

Working with Samba multiple concurrent(ish) asynchronous network functions much work is done with continuations or callback functions which are invoked when forwarded network'd rpc responses are returned.

Co-routines

I had previously tried another way of working this by writing in synchronous style using libpcl, and spawning such functions as a private coroutine.

With every rpc-send function Samba has an rpc-receive function which will block in a nested event loop until the response packet is received (if the response has not already been received).

I modified the nested event loop code to switch back to the main co-routine. The packet-received callback routine then just has to switch back to my private co-routine and the rpc-receive function would then return with the now received packet.

It worked well enough but highlighted other bugs which came to light when concurrency became possible; such as use of a connection before it is properly established.

The reason co-routines were used here at all was to obtain a private stack as a simple way to preserve state when waiting for the response, as well as aid debugging - after all a linear stack trace is nicer than a state-machine state any day!

But if the main aim is to protect the stack from being torn down and destroyed, why not allocate the stack frame on a heap? This would allow a function to return to the caller (in some fashion) while preserving state so that mid-re-entry could be achieved at the callback. This is what C#'s yield return does and is perhaps along the lines of native C-ish support for call-with-current-continuation from Scheme (or Lisp). It would not be a full implementation of course unless a full copy of the application environment were made - but we don't want to re-invoke the return path anyway.

So can lightweight fibres be built into C, using such notation as:

do_something_slow(int a, int b) {
  int answer = callback(ask_question(a));
  printf("Answer %d\n", answer);
}

heap(do_something_slow(a, b));
printf("Task started\n");

where control will return to print "Task started" but sometime later the answer will be printed?

Of the two magic words heap and callback, the word heap signifies that a new non-returning stack frame would be allocated and the word callback signifies that the function ask_question will receive a callback address in some form which would cause execution to continue on the next line. This looks all very hand-wavy but of course the callback mechanism would have to be standardized, probably based on the event-loop mechanism by which the callbacks would be delivered.

This all corresponds very closely to my original case where a callback function was explicitly provided to the async function, and the sole role of the callback function was to switch execution to the saved stack. Having called the async function we then switch to the main stack and therefore the process which invoked heap.

I'll post my libpcl code soon, it has some custom varargs task launchers.

Sunday, 14 April 2013

Come, friendly hell

I felt inspired to develop Betjeman's poem Slough after learning that over 55 millions babies had been killed since the end of the WWII. Did the Nazis just switch sides after all?
Come friendly hell and burn us now!
We're burning babies anyhow,
It's hardly worth you waiting now.
Swarm over, death

It's a work in progress, verse 2 addresses the institutions and their emblems of progress

Friday, 29 March 2013

Tricky

An answer to Dicky, by Robert Graves is Tricky, by Sam Liddicott

First the original poem, and then the answer.

DICKY by ROBERT GRAVES

Mother:
Oh, what a heavy sigh!
Dicky, are you ailing?

Dicky:
Even by this fireside, mother,
My heart is failing.

To-night, across the down,
   Whistling and jolly,
I sauntered out from town
   With my stick of holly.

Bounteous and cool from sea
   The wind was blowing,
Cloud shadows under the moon
   Coming and going.

I sang old roaring songs,
   Ran and leaped quick,
And turned home by St. Swithin's
   Twirling my stick.

And there as I was passing
   The churchyard gate,
An old man stopped me, 'Dicky,
   You're walking late.'

I did not know the man,
   I grew afeared
At his lean, lolling jaw,
   His spreading beard,

His garments old and musty,
   Of antique cut,
His body very lean and bony,
   His eyes tight shut.

Oh, even to tell it now
   My courage ebbs...
His face was clay, mother,
   His beard, cobwebs.

In that long horrid pause
   'Good-night,' he said,
Entered and clicked the gate,
   'Each to his bed.'

Mother:
Do not sigh or fear, Dicky.
   How is it right
To grudge the dead their ghostly dark
   And wan moonlight?

We have the glorious sun,
   Lamp and fireside.
Grudge not the dead their moon-beams
   When abroad they ride.

In my poem, I wished to tell the other side of a perhaps less fearful story.
Thinks aren't always what they seem, and sometimes, not even that.

Tricky, by Sam Liddicott


Uncle:
Oh, what a merry sound!
Ricky, are you chuckling?

Ricky:
This evening by this fire,
Uncle, My heart is laughing.

To-night, across the down,
   Whistling and jolly,
From town young Dicky sauntered
   With a stick of holly.

Bounteous and cool from sea
   The wind was blowing,
Cloud shadows under the moon
   Coming and going.

He sang old roaring songs,
   Ran, and leaping quick,
He turned home by St. Swithin's
   Twirling his stick.

And there as he was passing
   The churchyard gate,
Greeting him, I said: 'Dicky,
   You're walking late.'

I think he did not know me,
   He looked afeared
And my jaw, open fell,
   My theatre beard!

This outfit old and musty,
   Of antique cut!
I rocked in silent laugher,
   My eyes tight shut.

Oh, even to tell it now
   My humour rises...
His face was petrified,
   by costume trousers!

After an awkward pause
   'Good-night,' I said,
Passing through the churchyard gate,
   'Each to his bed.'

Uncle:
Do not laugh at fear, Ricky.
   How is it right
To terrify a little lad
   in the moonlight?

When by the glorious sun,
   Lamp and fireside.
 He knows you as a friend; so:
   Do not deride.

A long time ago I helped form the Open Rights Group.


Sunday, 3 February 2013

Forgiveness

I post this to point out that forgiveness isn't something available on demand, and also the dangers of letting the perpetrator define what forgiveness does and does not mean.

It can take the victim longer to work out forgiveness than it took the culprit to commit the offences and finally achieve a change of heart. This is something a repentant perpetrator may or may not be able to comprehend.

For example I might finally forgive my accountant for ripping me off and dashing my dreams and losing my house, but I wouldn't give him the chance to do it again, and I don't expect to be able stop suffering the injury and seeking revenge and punishment at his demand and admission. It would take time and effort and more time and more effort.

In other words I can eventually stop suffering from the injury, and I can eventually stop seeking revenge and punishment. But I don't have to give him access to my bank account in order to prove to him that I have reached or am trying to reach that state.

If someone thinks I haven't forgiven them, then that is their problem whether or not they are right. They just might have to forgive me.

Only the innocent victim knows what forgiveness entails, and only the repentant perpetrator wants it badly enough to wait for it.

And, for accuracy, there is one truly innocent victim who provides the means of healing and forgiveness for the injured and the guilty; when they want it badly enough to receive it.