This is a blog about me, Seinfeld, okonomiyaki, japanese toilet seats, and other things of interest

Thursday, May 15, 2008

Back to Basics: Part 2

As you've problably guessed, the problem is if the macro is used in if-statements. Consider this:

if(bla)
LOCK_CALL(library_func(libref, bla));
else
do_something_else();


This will be translated in to:
if(bla)
{lock(libref); library_func(libref, bla); unlock(libref);};
else
do_something_else();


See that last ';' on the macro line? That means that we have two statements on that line; the lock statement and the empty ';'. Hence this is not syntactically correct C as if you have more than one statement after an if-statement it should be in it's own block, like:

if(bla)
{
{lock(libref); library_func(libref, bla); unlock(libref);}
;
}
else
do_something_else();


How do we solve this? The do-while(0) trick to the rescue!

#define LOCK_CALL2(func) do {lock(libref); func; unlock(libref);} while(0)


This will be translated in to syntactically correct C both when used by itself and when used in an if-statement.

By now readers with attention to detail have found another flaw. "How about", they say, "if the function returns a value that you are interested in, then it won't work, Mr Smarty Pants". Well, they are correct, but there is an easy fix that solves at least part of the problem.

#define LOCK_CALL3(ret, func) do {lock(libref); ret = func; unlock(libref);} while(0)

int library_func(LIB* libref)

int ret_val;
LOCK_CALL3(ret_val, library_func));
// Now ret_val contains the return value


The only thing missing now is being able to call the function we want to lock from within an if-statement or such as the conditional,e.g.

if(LOCK_CALL(library_func(libref)))
do_stuff();
else
do_something_else();


That is left as an exercise to the reader. (In other words, I don't know how to do it!)

0 Comments:

Post a Comment

<< Home