State Machines and Coroutines

  • Follow


State Machines and Coroutines

The other thread on goto: Lead me to want to ask... In the spirit of 
state machines and coroutines, This n00b to C would like to know if 
setjmp/longjmp are the only way to break out of a routine; leave the 
function and re-enter the stack state.

I ask this because I've only briefly, as yet,  reviewed these functions 
and I believe longjmp will only return a designated int. Therefore I 
would naively assume pointers would/could be used to return or alter 
variables. I think I remember something mentioned about volatile 
qualifiers being used as well.

Thank you,
Deiter
0
Reply usenet.stuff (25) 1/4/2006 2:04:22 PM

Deiter wrote:
> State Machines and Coroutines
>
> The other thread on goto: Lead me to want to ask... In the spirit of
> state machines and coroutines, This n00b to C would like to know if
> setjmp/longjmp are the only way to break out of a routine; leave the
> function and re-enter the stack state.
>
> I ask this because I've only briefly, as yet,  reviewed these functions
> and I believe longjmp will only return a designated int. Therefore I
> would naively assume pointers would/could be used to return or alter
> variables. I think I remember something mentioned about volatile
> qualifiers being used as well.
>

Hi Deiter,
I'm not entirely sure what you are trying to do here, but it sounds
like you want to exit a function before you have reached the end?

You can exit a function at any point with the return(var) statment. For
example if your fundtion returns an integer you can call return(0).

e.g.

int test_fnc(int input)
{
   if (input >= 1)
      return (1);
   else
      return(0);
}

After the return statment the function is removed from the stack.
Hope that helps,
Alastair

0
Reply adadachanji (21) 1/4/2006 2:22:50 PM


Alastair wrote:
> Deiter wrote:
> 
>>State Machines and Coroutines
>>
>>The other thread on goto: Lead me to want to ask... In the spirit of
>>state machines and coroutines, This n00b to C would like to know if
>>setjmp/longjmp are the only way to break out of a routine; leave the
>>function and re-enter the stack state.
>>
>>I ask this because I've only briefly, as yet,  reviewed these functions
>>and I believe longjmp will only return a designated int. Therefore I
>>would naively assume pointers would/could be used to return or alter
>>variables. I think I remember something mentioned about volatile
>>qualifiers being used as well.
>>
> 
> 
> Hi Deiter,
> I'm not entirely sure what you are trying to do here, but it sounds
> like you want to exit a function before you have reached the end?
> 
> You can exit a function at any point with the return(var) statment. For
> example if your fundtion returns an integer you can call return(0).
> 
> e.g.
> 
> int test_fnc(int input)
> {
>    if (input >= 1)
>       return (1);
>    else
>       return(0);
> }
> 
> After the return statment the function is removed from the stack.
> Hope that helps,
> Alastair
> 

Hi, thanks Alastar but I'm a bit farther along than returns.

I believe setjmp allows you to "unwind" the stack to a prior position in 
the routine when longjmp is then called.

But I'm generally interested in how the experienced in C consider 
efficient state machines/coroutine structured programming.

Thanks
0
Reply usenet.stuff (25) 1/4/2006 2:36:56 PM

> Hi, thanks Alastar but I'm a bit farther along than returns.
>
> I believe setjmp allows you to "unwind" the stack to a prior position in
> the routine when longjmp is then called.
>
> But I'm generally interested in how the experienced in C consider
> efficient state machines/coroutine structured programming.
>
> Thanks

Hi Dieter,

Hmm... nearly everything I do in C is as part of state mechines, but I
have not come across a need to use setjmp / longjmp, we need every bit
of efficiency that we can get (in some cases).

I'll be interested to hear what other poeple have to say...

Do you have a simple example of what you are trying to achieve?

0
Reply adadachanji (21) 1/4/2006 3:26:18 PM

Deiter wrote:
>
> I think I remember something mentioned about volatile
> qualifiers being used as well.
>

Hi,

One usual use of "volatile" is to inform the compiler that the variable
can be changed by some code not created by it. In other words, the
value can change "alone". Setjmp/longjmp man pages refers to this flag.

That means, in a code like:
int x;
x=8;
.... /* x is not changed */
printf("%d",x);

the compiler could optimize to:
int x;
.... /* x is not changed */
printf("%d",8);

The volatile flag prevents the compiler to do not made this kind of
optimization.

Probably some other users of this group can provide more information.

Kind regards.

PS: Sorry if this is something well known by you. About the other part
of your query, I'm not sure of understand it.

0
Reply tmp123 (184) 1/4/2006 3:32:44 PM

Alastair wrote:
>>Hi, thanks Alastar but I'm a bit farther along than returns.
>>
>>I believe setjmp allows you to "unwind" the stack to a prior position in
>>the routine when longjmp is then called.
>>
>>But I'm generally interested in how the experienced in C consider
>>efficient state machines/coroutine structured programming.
>>
>>Thanks
> 
> 
> Hi Dieter,
> 
> Hmm... nearly everything I do in C is as part of state mechines, but I
> have not come across a need to use setjmp / longjmp, we need every bit
> of efficiency that we can get (in some cases).
> 
> I'll be interested to hear what other poeple have to say...
> 
> Do you have a simple example of what you are trying to achieve?
> 
I program in C for about 20 years, and I have yet to meet a case,
where I need to jump(or might want to).
And I hope I never have to learn how.
Before that time, I used fortran, and even there jump was mostly
to get the same result as continue and exit in C,so short,simple
forward jumps only ,to control loops,or to construct a case switch.
0
Reply burrynulnulfour (424) 1/4/2006 3:59:51 PM

Deiter wrote:
 >
> State Machines and Coroutines
> 
> The other thread on goto: Lead me to want to ask... In the
> spirit of state machines and coroutines, This n00b to C would
> like to know if setjmp/longjmp are the only way to break out of
> a routine; leave the function and re-enter the stack state.
> 
> I ask this because I've only briefly, as yet,  reviewed these
> functions and I believe longjmp will only return a designated
> int. Therefore I would naively assume pointers would/could be
> used to return or alter variables. I think I remember something
> mentioned about volatile qualifiers being used as well.

There is no such thing as a stack in C.  There are only various 
classes of storage (static, automatic, and allocated).  A stack may 
be used to implement automatic storage, but is not required.

After that the important thing to bear in mind is that after 
executing a longjmp only volatile storage items are accessible. 
 From N869:

   [#3]  All  accessible  objects  have  values  as of the time
   longjmp was called, except that the  values  of  objects  of
   automatic  storage  duration  that are local to the function
   containing the invocation of the corresponding setjmp  macro
   that  do  not  have  volatile-qualified  type  and have been
   changed between the setjmp invocation and longjmp  call  are
   indeterminate.

-- 
"If you want to post a followup via groups.google.com, don't use
  the broken "Reply" link at the bottom of the article.  Click on
  "show options" at the top of the article, then click on the
  "Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
0
Reply cbfalconer (19183) 1/4/2006 4:10:08 PM

Deiter wrote:
> State Machines and Coroutines
>
> The other thread on goto: Lead me to want to ask... In the spirit of
> state machines and coroutines, This n00b to C would like to know if
> setjmp/longjmp are the only way to break out of a routine; leave the
> function and re-enter the stack state.
>
> I ask this because I've only briefly, as yet,  reviewed these functions
> and I believe longjmp will only return a designated int. Therefore I
> would naively assume pointers would/could be used to return or alter
> variables. I think I remember something mentioned about volatile
> qualifiers being used as well.


Hi Deiter - read the topic (very recent) about using "Goto" - the
longjmp / setjmp are mentioned there with some comments later about
it's potencial use...

Alastair

0
Reply adadachanji (21) 1/4/2006 4:21:36 PM

Deiter wrote:
> State Machines and Coroutines
>
> The other thread on goto: Lead me to want to ask... In the spirit of
> state machines and coroutines, This n00b to C would like to know if
> setjmp/longjmp are the only way to break out of a routine; leave the
> function and re-enter the stack state.

Coroutines in C, by Simon Tatham:
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

He uses a technique similar to the famous Duff's Device to implement
coroutines as described by Knuth.

There's also the Protothreads library, which uses the technique to
implement a form of cooperative multithreading.
http://www.sics.se/~adam/pt/pt-1.0-refman/main.html

Josh

0
Reply sebasttj (24) 1/4/2006 5:03:07 PM

In article <oumdnZV8IMVASCbeRVn-sg@comcast.com>
Deiter  <usenet.stuff@comcast.net> wrote:
>The other thread on goto: Lead me to want to ask... In the spirit of 
>state machines and coroutines, This n00b to C would like to know if 
>setjmp/longjmp are the only way to break out of a routine;

As others noted, the answer to this question as stated is "no",
because ordinary "return" breaks out of a routine, returning to
its caller.  But the answer to the question I believe you intended
is "yes".

>leave the function and re-enter the stack state.

Given this and the subject line ("coroutines"), it sounds as though
you wish to use longjmp() to resume execution in a function that
earlier used setjmp() to terminate its own execution, e.g.:

    void f(void) {
        ... do some work ...
        if (setjmp(label1))
            goto resume;
        ... do some more work ...
        longjmp(label2, 1); /* "suspend" function f() */
    resume:
        ... do yet more work ...
        ... ordinary function-return here ...
    }

    void g(void) {
        ... do some work ...
        if (setjmp(label2))
            goto resume;
        ... do some more work ...
        f(); /* f() will longjmp to label2 */
        return;
    label2:
        /* we got here because f() executed a longjmp() */
        ... do more work ...
        longjmp(label1, 1); /* go back into f() */
        /* NOTREACHED */
    }

This is not "legal" in Standard C, and some implementations --
including more than one that I wrote myself -- will abort your
program at the "longjmp(label1, 1)" in g(), when they discover
that you are attempting to "reactivate" a stack frame that you
abandoned earlier (by executing the longjmp() in f()).

The key insight here is that longjmp() does not mean "suspend"; it
means "quit, and destroy all local variables".  To implement
coroutines, you must *not* destroy the local variables.  How this
can be done (and indeed, whether it is even possible) is
machine-dependent, and sometimes compiler-dependent.  The longjmp
function is not guaranteed to do this, and does not work on real
implementations.

>I ask this because I've only briefly, as yet, reviewed these functions 
>and I believe longjmp will only return a designated int.

This is correct; but the situation is considerably worse: longjmp()
may also destroy variables that are local to the function that used
setjmp().  To prevent this, such variables must be declared using
the "volatile" qualifier.  In addition, the return value from setjmp()
cannot be stored in a variable!  That is, the Standard renders the
effect of:

    int x; /* or even "volatile int x" */
    ...
    x = setjmp(jmpbuf);

undefined:

       Environmental restriction

       [#4] An invocation of the setjmp macro shall appear only  in
       one of the following contexts:

          - the entire controlling expression  of  a  selection  or
            iteration statement;

          - one operand of a relational or equality  operator  with
            the  other operand an integer constant expression, with
            the resulting expression being the  entire  controlling
            expression of a selection or iteration statement;

          - the operand of a unary ! operator  with  the  resulting
            expression being the entire controlling expression of a
            selection or iteration statement; or

           - the  entire  expression  of  an  expression  statement
            (possibly cast to void).

       [#5] If the invocation appears in  any  other  context,  the
       behavior is undefined.

What this means is that to use longjmp(), the programmer must in
general implement his own stack of activations, e.g.:

    struct Goto {
        struct Goto *next;
        volatile int longjmp_value1; /* can use volatile here */
        volatile char *longjmp_value2; /* to avoid needing it below */
        ... etc ...
        jmp_buf buf;
    };
    struct Goto *Goto_tos; /* current top of Goto stack */
    ...
    void f(void) {
        struct Goto g; /* need "volatile" if not in the struct */
        ...
        g.next = Goto_tos; /* push ourselves on the stack */
        Goto_tos = g;
        if (setjmp(g.buf))
            goto got_jumped_to;

        ... normal flow of control ...
        return;
    got_jumped_to:
        Goto_tos = g.next; /* pop ourselves off the stack */
        ... the value(s) from longjmp are in g.longjmp_valueN ...
        ... "gone-to" flow of control ...
    }

    void g(void) {
        ... normal flow of control ...
        if (some exceptional condition) {
            /* abort, ripping control away from all callers until top
               of goto stack */
            Goto_tos->longjmp_value1 = ...;
            Goto_tos->longjmp_value2 = ...;
            longjmp(Goto_tos->buf, 1);
        }
        ... continue normal flow of control ...
    }

Note that as soon as you start doing this, all functions involved
in the path between f() and g() that need to clean up (e.g., close
a file or free memory) start having to catch longjmp()s.  In this
case, the "goto stack" structure provides the same thing Lisp
systems provide via "unwind-protect".
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.29'W)  +1 801 277 2603
email: forget about it   http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
0
Reply nospam252 (1722) 1/4/2006 7:06:46 PM

Deiter wrote:
> State Machines and Coroutines
> 
> The other thread on goto: Lead me to want to ask... In the spirit of 
> state machines and coroutines, This n00b to C would like to know if 
> setjmp/longjmp are the only way to break out of a routine; leave the 
> function and re-enter the stack state.
> 
> I ask this because I've only briefly, as yet,  reviewed these functions 
> and I believe longjmp will only return a designated int. Therefore I 
> would naively assume pointers would/could be used to return or alter 
> variables. I think I remember something mentioned about volatile 
> qualifiers being used as well.
> 
> Thank you,
> Deiter

To all the responders:   Thank you.

Dieter
0
Reply usenet.stuff (25) 1/5/2006 10:03:17 AM

In article <dph6c60hcv@news1.newsguy.com> I wrote, in part:
>Given this and the subject line ("coroutines"), it sounds as though
>you wish to use longjmp() to resume execution in a function that
>earlier used setjmp() to terminate its own execution ...

That last line should read "earlier used longjmp()" (not setjmp()).

The example was correctly-invalid, though.

As one last note, it sometimes *is* possible to use longjmp to
implement coroutines (this depends on the system), but it is always
machine-dependent, and often best done as C-callable assembly
routines (i.e., often you should not even *attempt* to write the
coroutine routines in non-portable C -- it will be easier, not to
mention safer, to write them in the machine's assembly language).
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40�39.22'N, 111�50.29'W)  +1 801 277 2603
email: forget about it   http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
0
Reply nospam252 (1722) 1/8/2006 7:01:11 PM

11 Replies
17 Views

(page loaded in 0.349 seconds)


Reply: