Feel++ 0.91.0
Defines

/build/buildd/feel++-0.91.0~svn7013/feel/feelcore/feelmacros.hpp File Reference

Defines

#define FEEL_GNUC_AT_LEAST(x, y)   0
#define FEEL_CONSTRUCTOR_BEGIN(Area, A)   Debug( Area ) << "Constructor of " << A << " begins\n";
#define FEEL_CONSTRUCTOR(Area, A)   FEEL_CONSTRUCTOR_BEGIN(Area,A)
#define CONSTRUCTOR(A)   FEEL_CONSTRUCTOR_BEGIN(20000,A)
#define FEEL_CONSTRUCTOR_END(Area, A)   Debug( Area ) << "Constructor of " << A << " ends\n";
#define FEEL_DESTRUCTOR_BEGIN(Area, A)   Debug( Area ) << "Destructor of " << A << " begins\n";
#define FEEL_DESTRUCTOR(Area, A)   FEEL_DESTRUCTOR_END(Area,A)
#define DESTRUCTOR(A)   FEEL_DESTRUCTOR_BEGIN(20000,A)
#define FEEL_DESTRUCTOR_END(Area, A)   Debug( Area ) << "Destructor of " << A << " ends\n";
#define INLINE   inline
#define FEEL_RESTRICT   __restrict__
 C99 feature of restricted(not aliased) pointers and references.
#define FEEL_EXPORT
 Load time improvements for DSO libraries.
#define FEEL_NO_EXPORT
#define FEEL_PACKED
#define FEEL_DEPRECATED
#define FEEL_ISLIKELY(x)   ( x )
#define FEEL_ISUNLIKELY(x)   ( x )
#define FEEL_PREFETCH(x, rw, locality)
 Prefetching.
#define FEEL_IS_CONSTANT(n)
 detect at compile if it is a constant
#define FEEL_DEBUG_VAR(x)   std::cerr << #x << " = " << x << std::endl;
#define FEEL_ALWAYS_INLINE_ATTRIB
#define FEEL_STRONG_INLINE   inline
#define FEEL_DONT_INLINE

Detailed Description

Author:
Christophe Prud'homme <christophe.prudhomme@ujf-grenoble.fr>
Date:
2005-01-24

Define Documentation

#define FEEL_CONSTRUCTOR_BEGIN (   Area,
 
)    Debug( Area ) << "Constructor of " << A << " begins\n";

Inform that the constructor of the class x has started

#define FEEL_CONSTRUCTOR_END (   Area,
 
)    Debug( Area ) << "Constructor of " << A << " ends\n";

Inform that the constructor of the class x has ended

#define FEEL_DEPRECATED

The FEEL_DEPRECATED macro can be used to trigger compile-time warnings with gcc >= 3.2 when deprecated functions are used.

For non-inline functions, the macro gets inserted at the very end of the function declaration, right before the semicolon:

   DeprecatedConstructor() FEEL_DEPRECATED;
   void deprecatedFunctionA() FEEL_DEPRECATED;
   int deprecatedFunctionB() const FEEL_DEPRECATED;

Functions which are implemented inline are handled differently: for them, the FEEL_DEPRECATED macro is inserted at the front, right before the return type, but after "static" or "virtual":

   FEEL_DEPRECATED void deprecatedInlineFunctionA() { .. }
   virtual FEEL_DEPRECATED int deprecatedInlineFunctionB() { .. }
   static FEEL_DEPRECATED bool deprecatedInlineFunctionC() { .. }
   \end

   You can also mark whole structs or classes as deprecated, by inserting the
   FEEL_DEPRECATED macro after the struct/class keyword, but before the
   name of the struct/class:

   \code
   class FEEL_DEPRECATED DeprecatedClass { };
   struct FEEL_DEPRECATED DeprecatedStruct { };
#define FEEL_DESTRUCTOR_BEGIN (   Area,
 
)    Debug( Area ) << "Destructor of " << A << " begins\n";

Inform that the destructor of the class x has started

#define FEEL_DESTRUCTOR_END (   Area,
 
)    Debug( Area ) << "Destructor of " << A << " ends\n";

Inform that the destructor of the class x has started

#define FEEL_EXPORT

Load time improvements for DSO libraries.

Here are a few explanations why this is useful. For more info checkout http://www.nedprod.com/programs/gccvisibility.html

  1. It very substantially improves load times of your DSO (Dynamic Shared Object) For example, the TnFOX Boost.Python bindings library now loads in eight seconds rather than over six minutes!
  1. It lets the optimiser produce better code PLT indirections (when a function call or variable access must be looked up via the Global Offset Table such as in PIC code) can be completely avoided, thus substantially avoiding pipeline stalls on modern processors and thus much faster code. Furthermore when most of the symbols are bound locally, they can be safely elided (removed) completely through the entire DSO. This gives greater latitude especially to the inliner which no longer needs to keep an entry point around "just in case".
  1. It reduces the size of your DSO by 5-20% ELF's exported symbol table format is quite a space hog, giving the complete mangled symbol name which with heavy template usage can average around 1000 bytes. C++ templates spew out a huge amount of symbols and a typical C++ library can easily surpass 30,000 symbols which is around 5-6Mb! Therefore if you cut out the 60-80% of unnecessary symbols, your DSO can be megabytes smaller!
  1. Much lower chance of symbol collision The old woe of two libraries internally using the same symbol for different things is finally behind us with this patch. Hallelujah!

here is an example on how to use them

   int FEEL_NO_EXPORT foo;
   int FEEL_EXPORT bar;

   extern "C" FEEL_EXPORT void function(int a);

   class FEEL_EXPORT SomeClass
   {
     int c;

     // Only for use within this DSO
     FEEL_NO_EXPORT void privateMethod();

    public:

     Person(int _c) : c(_c) { }
     static void foo(int a);
    };
#define FEEL_IS_CONSTANT (   n)

detect at compile if it is a constant

GCC provides a built-in function that you can use to determine whether a value is a constant at compile-time. This is valuable information because you can construct expressions that can be optimized through constant folding. The __builtin_constant_p function is used to test for constants.

The prototype for __builtin_constant_p is shown below. Note that __builtin_constant_p cannot verify all constants, because some are not easily proven by GCC.

 int __builtin_constant_p( exp )

Linux uses constant detection quite frequently. In the example shown in Listing 3 (from ./linux/include/linux/log2.h), constant detection is used to optimize the roundup_pow_of_two macro. If the expression can be verified as a constant, then a constant expression (which is available for optimization) is used. Otherwise, if the expression is not a constant, another macro function is called to round up the value to a power of two.

Listing. Constant detection to optimize a macro function

#define roundup_pow_of_two(n)                   \
(                                               \
        __builtin_constant_p(n) ? (             \
                (n == 1) ? 1 :                  \
                (1UL << (ilog2((n) - 1) + 1))   \
                                   ) :          \
        __roundup_pow_of_two(n)                 \
)
#define FEEL_ISLIKELY (   x)    ( x )

The FEEL_ISLIKELY macro tags a boolean expression as likely to evaluate to 'true'. When used in an if ( ) statement, it gives a hint to the compiler that the following codeblock is likely to get executed. Providing this information helps the compiler to optimize the code for better performance. Using the macro has an insignificant code size or runtime memory footprint impact. The code semantics is not affected.

Note:
Providing wrong information ( like marking a condition that almost never passes as 'likely' ) will cause a significant runtime slowdown. Therefore only use it for cases where you can be sure about the odds of the expression to pass in all cases ( independent from e.g. user configuration ).
The FEEL_ISUNLIKELY macro tags an expression as unlikely evaluating to 'true'.
Note:
Do NOT use ( !FEEL_ISLIKELY(foo) ) as an replacement for FEEL_ISUNLIKELY !
   if ( FEEL_ISUNLIKELY( testsomething() ) )
       abort();     // assume its unlikely that the application aborts
#define FEEL_ISUNLIKELY (   x)    ( x )

Counterpart to FEEL_ISLIKELY The FEEL_ISUNLIKELY macro tags an expression as unlikely evaluating to 'true'.

#define FEEL_NO_EXPORT

Counterpart to FEEL_EXPORT.

#define FEEL_PACKED

The FEEL_PACKED can be used to hint the compiler that a particular structure or class should not contain unnecessary paddings.

Here is an explanation from http://sig9.com/articles/gcc-packed-structures

GCC allows you to specify attributes of variables and structures using the keyword __attribute__, the syntax of which is __attribute__((attribute list)). One such attribute is __packed__ which specifies that

a variable or structure field should have the smallest possible alignment--one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.

which means that GCC will not add any of the zero's for padding (for memory alignement) and make variables or fields immediately next to each other. For example, here are some things I tried out -- I created a C source file - test.c

   struct test_t {
   int  a;
   char b;
   int  c;
   } ;

   struct test_t test = { 10, 20, 30};

And compiled it with the -S option (ie to generate the assembly equivalent of the code generated).

      .file "t.cpp"
      .globl test
        .data
        .align 4
        .type test, @object
        .size test, 12
      <b>test:
      .long 10
      .byte 20
      .zero 3
      .long 30</b>
      .section .note.GNU-stack,"",@progbits
      .ident   "GCC: (GNU) 3.3.5 (Debian 1:3.3.5-6)"

Notice the emphasized code. You can see that the structure "test" is being declared. First the field "a" (int) as .long 10 followed by "b" (char) as .byte 20. To keep the fields' word alignment, notice that GCC has added 3 zero bytes (.zero 3) before field "c" (int) which is declared as .long 30. This makes the effective sizeof struct test_t as 12 instead of the expected 9. Then I tried with the __packed__ attribute -

   struct test_t {
   int  a;
   char b;
   int  c;
   } FEEL_PACKED

   struct test_t test = { 10, 20, 30};

and the "-S" output I got after compiling was

   .file "t.cpp"
   .globl test
     .data
     .type test, @object
     .size test, 9
   test:
     .long 10
     .byte 20
     .long 30
   .section .note.GNU-stack,"",@progbits
   .ident   "GCC: (GNU) 3.3.5 (Debian 1:3.3.5-6)"

in which the zeros are missing making the sizeof structure test_t = 9. Always remember that memory alignment is *good* even if it compromises space, so think twice before using this attribute. It is generally useful when you want to assign a structure to a block of memory and manipulate it through the fields of a structure.

#define FEEL_PREFETCH (   x,
  rw,
  locality 
)

Prefetching.

Another important method of improving performance is through caching of necessary data close to the processor. Caching minimizes the amount of time it takes to access the data. Most modern processors have three classes of memory:

  1. Level 1 cache commonly supports single-cycle access
  1. Level 2 cache supports two-cycle access
  1. System memory supports longer access times

To to minimize access latency, and thus improve performance, it's best to have your data in the closest memory. Performing this task manually is called prefetching. GCC supports manual prefetching of data through a built-in function called __builtin_prefetch. You use this function to pull data into the cache shortly before it's needed. As shown below, the __builtin_prefetch function takes three arguments:

  1. The address of the data
  1. The rw parameter, which you use to indicate whether the data is being pulled in for Read or preparing for a Write operation
  1. The locality parameter, which you use to define whether the data should be left in cache or purged after use
 void  __builtin_prefetch( const void *addr, int rw, int locality );

Prefetching is used extensively by the Linux kernel. Most often it is used through macros and wrapper functions. Listing below is an example of a helper function that uses a wrapper over the built-in function (from ./linux/include/linux/prefetch.h). The function implements a preemptive look-ahead mechanism for streamed operations. Using this function can generally result in better performance by minimizing cache misses and stalls.

 #ifndef ARCH_HAS_PREFETCH
 #define prefetch(x) __builtin_prefetch(x)
 #endif

 static inline void prefetch_range(void *addr, size_t len)
 {
 #ifdef ARCH_HAS_PREFETCH
 char *cp;
 char *end = addr + len;

 for (cp = addr; cp < end; cp += PREFETCH_STRIDE)
   prefetch(cp);
 #endif
 }
#define FEEL_RESTRICT   __restrict__

C99 feature of restricted(not aliased) pointers and references.

As with gcc, g++ understands the C99 feature of restricted pointers, specified with the __restrict__, or __restrict type qualifier. Because you cannot compile C++ by specifying the -std=c99 language flag, restrict is not a keyword in C++.

In addition to allowing restricted pointers, you can specify restricted references, which indicate that the reference is not aliased in the local context.

   void fn (int *__restrict__ rptr, int &__restrict__ rref)
   {
   ...
   }

In the body of fn, rptr points to an unaliased integer and rref refers to a (different) unaliased integer.

You may also specify whether a member function's this pointer is unaliased by using __restrict__ as a member function qualifier.

   void T::fn () __restrict__
   {
   ...
   }

Within the body of T::fn, this will have the effective definition T* __restrict__ const this. Notice that the interpretation of a __restrict__ member function qualifier is different to that of const or volatile qualifier, in that it is applied to the pointer rather than the object. This is consistent with other compilers which implement restricted pointers.

As with all outermost parameter qualifiers, __restrict__ is ignored in function definition matching. This means you only need to specify __restrict__ in a function definition, rather than in a function prototype as well.

In order to ensure that the code is portable to other compiler than gcc/g++ a macro has been defined FEEL_RESTRICT that is equal to __restrict__ if the compiler supports it.

#define INLINE   inline

Alias to the C/C++ keyword inline