[En-Nut-Discussion] Using boost::preprocessor (preprocessor metaprogramming)

duane ellis ethernut at duaneellis.com
Wed Feb 11 13:20:27 CET 2009


thiago> [earlier] [ use of boost macros ]
thiago> It also follows the DRY principle

Hmm... I'd disagree, macro expansion on this scale is repeating your self.

I see value in the BOOST macros, *WHEN* things need to be independent 
functions. 

That is not the case here.

There is an old saying a fellow developer I worked with had - it is a 
great and wonderful way of looking at it.

   Do not show me your code.
   Show me your data structures
   The data structures will explain your code.

I don't know where it came from.

henrik> [earlier] Maybe some smaller examples would help ....

thaigo>  GpioPinSet(SBBI0_CS0_PORT, SBBI0_CS0_BIT, hi);
thaigo>  GpioPinSet(SBBI0_CS1_PORT, SBBI0_CS1_BIT, hi);
thaigo>  GpioPinSet(SBBI0_CS2_PORT, SBBI0_CS2_BIT, hi);
thaigo>  GpioPinSet(SBBI0_CS3_PORT, SBBI0_CS3_BIT, hi);

Why is this not table driven? or parameterized, maybe pass a pointer to 
a structure with this sort of information in the structure, or something 
like that?.

Instead of 5 functions:   uart1_write()  through write5_write(),

int
uartX_write( int who, int c )
{
     UART_REGS  *p_uart = uart_pointer_table[ who ];
   ..... code .....
}

That "uartX_write()" function is functionally identical to:  fputc(), by 
doing it that way, one can support any number of "open files" or in this 
example, uarts, you can make legacy code work - create uart0_write(), 
that calls uartX_write() passing the correct parameter for "X".

Please don't mis-understand me - having the "uart_write()" [which calls 
uartX_write()] makes sense if you have a very common UART that is used 
for everything. [See parameter passing code size reduction below]

In your example, instead of "boiler plate code" inside a switch 
statement, why is it not parameterized into a table like this:

GPioSPi0ChipSelect(  uint8_t cs, int hi )
{
      if( cs < SOME_VALUE_N_PINS ){
            GpioPinSet(  foo[cs].pin, foo[cs].bit, hi );
            GpioPinConfigSet( foo[cs].port, foo[cs].bit,  GPIO_CFG_OUTPUT );
           return foo[cs].gspi_reg_ptr;
       } else {
             errno = EIO;
             return NULL;
      }
}
 

More importantly, these are embedded devices. The above TABLE driven 
approach I believe results in a smaller code foot print then the BOOST 
macros (which run on huge machines that can manage bloat).

Lastly, when ever I see code that calls several functions in a row, it 
*screams* refactor to me, for example the two GPIO functions *SCREAM* 
for a function that perhaps looks like this:

       GpioSetOutput(  int PIN_ID,  int VALUE )

Which - from the PIN_ID calculates the "port" and "bit" value, and sets 
the direction - thus resulting in even smaller code, for example: 
"PIN_ID div 8" = port number,  (1 << (PIN_ID mod 8)) = bitnumber.  Or is 
table driven.  That function would of course - both *SET* and *CONFIG* 
the pin in the proper way.

I'll bet those two functions are used over and over again in pairs in 
other places in other places in the code. This type of refactoring would 
also reduce overall code size even more.

Another small item - by passing less parameters to a function, the 
overall code size shrinks. There is less 'setup' required before each 
function call. And less "messing with parameters" in the function entry 
code. There is also less run time stack usage. In this case, I believe 
you are porting to an avr32 platform, perhaps passing a larger parameter 
(which costs nothing extra in code space) is another approach. The 
underlying machines here is not 8 bit like an 8051.

Lastly: maybe there is something about the chip I don't know.  Is there 
a specific reason why the pin must be reconfigured every time you set it 
as an output? That seems odd, and a waste of time.  If true, that change 
would improve overall speed/performance - yes, only slightly. 

These are many little things that add up - here in the US - I'd use the 
phrase: "The straw that broke the camel's back"

http://en.wikipedia.org/wiki/Last_straw

-Duane.




More information about the En-Nut-Discussion mailing list