FYI, the new kernel newbie column is out
Eric Battersby
gyre-Ja3L+HSX0kI at public.gmane.org
Fri Jul 10 08:30:46 UTC 2009
On Wed, 8 Jul 2009, Alex Beamish wrote:
> With a couple of years of Perl development on top of a couple more
> years of C development, I'd propose using a table and some pointers:
>
> ======================================
> /* Prototype the registration functions. */
>
> int register_this(void *, char *);
> int register_that(void *, char *);
> int register_those(void *, char *);
> int unregister_this(void *, char *);
> int unregister_that(void *, char *);
>
> /* Define a skull element structure that contains a void pointer for a return
> * value, as well as pointers to the functions that register and unregister.
> * */
>
> typedef struct {
> void *pv;
> int (*pfiRegister)();
> int (*pfiUnRegister)();
> } SKULL_ELEMENT;
>
> /* Define an array of skull elements and initialize them with function
> * pointers or NULLs. */
>
> SKULL_ELEMENT astrStack[3] = {
> NULL, register_this, unregister_this,
> NULL, register_that, unregister_that,
> NULL, register_those, NULL,
> };
>
> int registration ()
> {
> SKULL_ELEMENT *pstr;
>
> /* Cycle through each the skull elements .. */
>
> for ( pstr = astrStack; pstr <= &astrStack[2]; pstr++ ) {
>
> /* Try to register a skull using the appropriate pointer and function ..
> * */
>
> int err = pstr->pfiRegister ( pstr->pv, "skull" );
> if ( err ) {
>
> /* If there was an error, go back through the stack and unregister any
> * prior registrations, and return the error. */
>
> while ( --pstr > astrStack ) {
>
> pstr->pfiUnRegister ( pstr->pv, "skull" );
>
> }
> return ( err );
> }
> }
>
> /* Success! */
>
> return ( 0 );
> }
> ======================================
>
> I prefer the usage of 'if ( err )' rather than the somewhat
> counterintuitive 'if ( !err )', but that's probably a matter for
> discussion over beer, and not a mailing list.
>
> It looks like this code tries to register with three different
> functions, and if any of them fail, it unregisters from any that
> succeeded. I note that there are no tests for failure on
> unregistration -- perhaps they were removed from the example code for
> clarity.
>
> I didn't have the time to actually confirm that my code is
> functionally the same, but it does compile. I think I last used
> function pointers in C back in 1998, so I'm not positive I have the
> syntax right, but the meaning should be clear enough.
That code still looks a bit hairy to me.
Using a stack abstraction,
I think the actual code logic is easier to understand
and becomes easier to read.
This code is functionally the same as the orginal.
***
...
/* do single registration here */
int reg_it( int(* reg)(char *p, char *s)
, int(*unreg)(char *p, char *s)
, char *p, char *s) {
int err;
err = reg( p, s );
if (err) { pop_all(); } /* undo previous registrations */
else { push( unreg, p, s ); } /* save new unregistration fn */
return( err );
}/* reg_it() */
/* macro to simplify relevant code and eliminate duplication */
#define REG_IT_OR_RETURN(name,ptr,str) \
err = reg_it(register_##name , unregister_##name , ptr, str); \
if ( err ) return(err);
/* MAIN CODE LOGIC */
int proc(char *ptr1, char *ptr2, char *ptr3) {
int err;
gREG_stack_inx = 0; /* reset stack */
/* do registration with undo */
REG_IT_OR_RETURN( this , ptr1, "skull");
REG_IT_OR_RETURN( that , ptr2, "skull");
REG_IT_OR_RETURN( those, ptr3, "skull");
return 0;
}/* proc() */
--
Eric Battersby
--
The Toronto Linux Users Group. Meetings: http://gtalug.org/
TLUG requests: Linux topics, No HTML, wrap text below 80 columns
How to UNSUBSCRIBE: http://gtalug.org/wiki/Mailing_lists
More information about the Legacy
mailing list