[comp.lang.c] setjmp/longjmp instead of goto

chris@mimsy.umd.edu (Chris Torek) (05/02/90)

>>In article <177@spodv2.UUCP> jha@spodv2.UUCP (Johan Harsta) writes:
>>> - Is performance really an issue in the majority of error situations?

>In article <949@tmiuv0.uucp> rick@tmiuv0.uucp suggests:
>>... if it's a recoverable error, yes, performance is important.
>>In that case, an error isn't really an "error", it's a condition that's not
>>normally run into.  You should handle errors gracefully in any case.

In article <35829@think.Think.COM> barmar@think.com (Barry Margolin) writes:
>If it's "not normally run into", then why is performance an issue?

Here is an example of how setjmp/longjmp can be used to finagle performance
by eliminating tests from inner loops:

	void somefunc(void) {
		int ret;
		while ((ret = setjmp(catch)) != 0) {
			if (ret == DONE)
				return;
			(void) printf("something happened, recovering...\n");
			recover();
		}
		work_hard();
	}

	void work_hard(void) {
		register char *p;
		register int n;
		char buf[SIZE];

		for (;;) {
			n = slowstuff(p = buf, SIZE);
			while (--n >= 0)
				inner_loop_code(*p++);
		}
	}

If the `error' occurs only while doing `slowstuff' (as does the DONE
condition), the test for the error can be relegated to the slow (and
infrequently called) `slowstuff' function.  The inner loop code can
ignore the possibility of errors.

It is worth noting that in all cases, such code can be restructured
to make the non-local goto unnecessary.  For example:

		for (;;) {
			n = slowstuff(p = buf, SIZE);
			if (n < 0)	/* e.g., DONE, ERR1, ERR2 */
				return n;
			while (--n >= 0)
				inner_loop_code(*p++);
		}

This usually has a negligible effect on both code size and run time,
and tends to be easier to understand.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris