472,119 Members | 1,483 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,119 software developers and data experts.

setjmp/longjmp and some table tennis

Hi,

I'm learning to use the setjmp/longjmp functions and still can't
really grasp what's going on here. I'd basically like to be able to
jump back and forth from (or to) two given functions.

Let's consider the following toy-example (yes, the example is stupid
but never mind...)

BEGIN CODE =====================
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>

void wrapper();
void ping(jmp_buf, jmp_buf);
void pong(jmp_buf, jmp_buf);

int main() {
wrapper();
return 0;
}
void ping(jmp_buf ping_env, jmp_buf pong_env) {
printf("calling ping\n");
switch (setjmp(ping_env)) {
case 0:
printf("ping: case 0\n");
pong(ping_env, pong_env);
break;
case 1:
printf("ping: case 1\n");
longjmp(pong_env, 1);
break;
case 2:
printf("ping: case 2\n");
longjmp(pong_env, 2);
break;
default:
printf("ping: case default\n");
break;
}
printf("ping is done\n");
}
void pong(jmp_buf ping_env, jmp_buf pong_env) {
printf("\tcalling pong\n");
switch (setjmp(pong_env)) {
case 0:
printf("\tpong: case 0\n");
longjmp(ping_env, 1);
break;
case 1:
printf("\tpong: case 1\n");
longjmp(ping_env, 2);
break;
case 2:
printf("\tpong: case 2\n");
longjmp(ping_env, 3);
break;
default:
printf("\tpong: case default\n");
break;
}
printf("pong is done\n");
}
void wrapper() {
jmp_buf pong_env;
jmp_buf ping_env;
ping(ping_env, pong_env);
}
END CODE ========================

This code works OK if I make ping_env and pong_env static global
variables. However, when I try to pass them as parameters the code
crash with a "Bus error".

Any explanation as to why it crashes? (Well, I guess that's because
the jmp_buf variables passed as parameters are somehow not properly
restored, but I'm new to this so...)

And, even better, any advise on how to correct this while keeping the
intent of the program? (Yeah, I know any real-life application of this
pattern would yield pretty awful code but that's not the matter
here...)

Thanks,

nch

Feb 23 '07 #1
3 1810
In article <11**********************@q2g2000cwa.googlegroups. com>,
<no************@yahoo.comwrote:
>Hi,

I'm learning to use the setjmp/longjmp functions and still can't
really grasp what's going on here. I'd basically like to be able to
jump back and forth from (or to) two given functions.
Then setjmp/longjmp is the wrong tool for the job. You're only allowed
to longjmp back to a setjmp in a stack frame that's still live.

>And, even better, any advise on how to correct this while keeping the
intent of the program? (Yeah, I know any real-life application of this
pattern would yield pretty awful code but that's not the matter
here...)
You want coroutines. They're not directly supported by C (or, for
that matter, by a lot of other languages); there are ways to do it
using correct and portable C code, but they're all Rather Ugly and/or
quite limited.

If you don't mind giving up portability, using threads to fake it might
be the cleanest solution, even though they're kind of heavyweight for
something like this (and they'll take a bit of care to get right).
dave

--
Dave Vandervies dj******@csclub.uwaterloo.ca
Always assume that your code will need to be maintained -- and that the
next person to work on it is a homocidal maniac who knows where you live.
--Keith Thompson in comp.lang.c
Feb 23 '07 #2
Dave Vandervies writes:
You want coroutines. They're not directly supported by C (or, for
that matter, by a lot of other languages); there are ways to do it
using correct and portable C code, but they're all Rather Ugly and/or
quite limited.
In this case it's simple enough. Let ping() and pong return the value
to be passed to each other, and write a controlling function which calls
them.

For more complicated examples it gets uglier, yes. E.g. let ping() and
pong() fill a struct with a pointer to the next function to be called
and its arguments, and the controlling function would call via that
struct. Or set an integer representing what to do next, and write
the controlling function as a state machine.

--
Regards,
Hallvard
Feb 23 '07 #3

<no************@yahoo.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
Hi,

I'm learning to use the setjmp/longjmp functions and still can't
really grasp what's going on here. I'd basically like to be able to
jump back and forth from (or to) two given functions.
<snip>
And, even better, any advise on how to correct this while keeping the
intent of the program? (Yeah, I know any real-life application of this
pattern would yield pretty awful code but that's not the matter
here...)
Don't use a screwdriver when a pair of pliers is called for.
Use something patterned like this:

typedef void (*Bouncer)( /*whatever needs passing*/ );

void ping( /*whatever needs passing*/ );
void pong( /*whatever needs passing*/ );
....
Bouncer next = NULL;
while (1) {
next = (next==ping) ? pong : ping;
(*next) (/*whatever needs passing*/ );
}
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Aero Stability and Controls Computing
Feb 23 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Thomas Baruchel | last post: by
12 posts views Thread by Michael B Allen | last post: by
4 posts views Thread by Jrferguson | last post: by
5 posts views Thread by candy | last post: by
20 posts views Thread by JS | last post: by
8 posts views Thread by Zheng Da | last post: by
15 posts views Thread by rover8898 | last post: by
4 posts views Thread by nicho | last post: by
5 posts views Thread by Spiros Bousbouras | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.