Logo  0.95.0-final
Finite Element Embedded Library and Language in C++
Feel++ Feel++ on Github Feel++ community
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
feelmacros.hpp File Reference

Go to the source code of this file.

Macros

#define CONSTRUCTOR(A)   FEELPP_CONSTRUCTOR_BEGIN(A)
 
#define DESTRUCTOR(A)   FEELPP_DESTRUCTOR_BEGIN(A)
 
#define FEELPP_ALWAYS_INLINE_ATTRIB
 
#define FEELPP_CLANG_AT_LEAST(x, y)   0
 
#define FEELPP_CONSTRUCTOR(A)   FEELPP_CONSTRUCTOR_BEGIN(A)
 
#define FEELPP_CONSTRUCTOR_BEGIN(A)   DVLOG(3) << "Constructor of " << A << " begins\n";
 
#define FEELPP_CONSTRUCTOR_END(A)   DVLOG(3) << "Constructor of " << A << " ends\n";
 
#define FEELPP_DEBUG_VAR(x)   std::cerr << #x << " = " << x << std::endl;
 
#define FEELPP_DEPRECATED
 
#define FEELPP_DESTRUCTOR(A)   FEELPP_DESTRUCTOR_END(A)
 
#define FEELPP_DESTRUCTOR_BEGIN(A)   DVLOG(3) << "Destructor of " << A << " begins\n";
 
#define FEELPP_DESTRUCTOR_END(A)   DVLOG(3) << "Destructor of " << A << " ends\n";
 
#define FEELPP_DONT_INLINE
 
#define FEELPP_EXPORT
 Load time improvements for DSO libraries. More...
 
#define FEELPP_GNUC_AT_LEAST(x, y)   0
 
#define FEELPP_IS_CONSTANT(n)
 detect at compile if it is a constant More...
 
#define FEELPP_ISLIKELY(x)   ( x )
 
#define FEELPP_ISUNLIKELY(x)   ( x )
 
#define FEELPP_NO_EXPORT
 
#define FEELPP_PACKED
 
#define FEELPP_PREFETCH(x, rw, locality)
 Prefetching. More...
 
#define FEELPP_RESTRICT   __restrict__
 C99 feature of restricted(not aliased) pointers and references. More...
 
#define FEELPP_STRONG_INLINE   inline
 
#define INLINE   inline
 

Detailed Description

Macro Definition Documentation

#define FEELPP_CONSTRUCTOR_BEGIN (   A)    DVLOG(3) << "Constructor of " << A << " begins\n";

Inform that the constructor of the class x has started

#define FEELPP_CONSTRUCTOR_END (   A)    DVLOG(3) << "Constructor of " << A << " ends\n";

Inform that the constructor of the class x has ended

#define FEELPP_DEPRECATED

The FEELPP_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() FEELPP_DEPRECATED;
void deprecatedFunctionA() FEELPP_DEPRECATED;
int deprecatedFunctionB() const FEELPP_DEPRECATED;

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

FEELPP_DEPRECATED void deprecatedInlineFunctionA() { .. }
virtual FEELPP_DEPRECATED int deprecatedInlineFunctionB() { .. }
static FEELPP_DEPRECATED bool deprecatedInlineFunctionC() { .. }
\end
You can also mark whole structs or classes as deprecated, by inserting the
FEELPP_DEPRECATED macro after the struct/class keyword, but before the
name of the struct/class:
\code
class FEELPP_DEPRECATED DeprecatedClass { };
struct FEELPP_DEPRECATED DeprecatedStruct { };
#define FEELPP_DESTRUCTOR_BEGIN (   A)    DVLOG(3) << "Destructor of " << A << " begins\n";

Inform that the destructor of the class x has started

#define FEELPP_DESTRUCTOR_END (   A)    DVLOG(3) << "Destructor of " << A << " ends\n";

Inform that the destructor of the class x has started

#define FEELPP_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!
  2. 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".
  3. 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!
  4. 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 FEELPP_EXPORT bar;
extern "C" FEELPP_EXPORT void function(int a);
class FEELPP_EXPORT SomeClass
{
int c;
// Only for use within this DSO
FEELPP_NO_EXPORT void privateMethod();
public:
Person(int _c) : c(_c) { }
static void foo(int a);
};
#define FEELPP_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 FEELPP_ISLIKELY (   x)    ( x )

The FEELPP_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 FEELPP_ISUNLIKELY macro tags an expression as unlikely evaluating to 'true'.
Note
Do NOT use ( !FEELPP_ISLIKELY(foo) ) as an replacement for FEELPP_ISUNLIKELY !
if ( FEELPP_ISUNLIKELY( testsomething() ) )
abort(); // assume its unlikely that the application aborts
#define FEELPP_ISUNLIKELY (   x)    ( x )

Counterpart to FEELPP_ISLIKELY The FEELPP_ISUNLIKELY macro tags an expression as unlikely evaluating to 'true'.

#define FEELPP_NO_EXPORT

Counterpart to FEELPP_EXPORT.

#define FEELPP_PACKED

The FEELPP_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;
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 =

  1. 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 FEELPP_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
  2. Level 2 cache supports two-cycle access
  3. 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
  2. The rw parameter, which you use to indicate whether the data is being pulled in for Read or preparing for a Write operation
  3. 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 FEELPP_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 FEELPP_RESTRICT that is equal to restrict if the compiler supports it.

#define INLINE   inline

Alias to the C/C++ keyword inline


Generated on Sun Dec 22 2013 13:11:15 for Feel++ by doxygen 1.8.5