Flip Configuration Guide

Miscellaneous Configuration

This chapter describes several preprocessor macros used to change specific behavior of the Flip framework.

flip_FATAL_MODE

When the Flip framework encounters an operation that put its state to subsequent undefined behavior, it will general a fatal error. The flip_FATAL_MODE will control how this fatal error is generated. It is for example used when the framework is able to detect an incorrect use of its API.

One will activate one option or another using the processor macros or definitions. For example :

flip_FATAL_MODE=flip_FATAL_MODE_THROW

flip_FATAL can be defined in a user specific way. To do this define flip_FATAL_MODE to flip_FATAL_MODE_USER and provide a definition of it using a compiler option. The best way though is to provide a user config file flip_user_config.h somewhere in the header search path of the compiler and define flip_HAS_FLIP_USER_CONFIG_H.

For example such a flip_user_config.h could look like this:

#pragma once
#include <cassert>
extern void trace_error(char* msg);
#define flip_FATAL { trace_error("FATAL!"); assert(false); throw; }

Important: Since flip_FATAL is used as a terminate function, the implementation must make sure that it is never returning. The throw in the example above ensures this.

flip_NOTHING

Values such as Int, Float or Blob in the flip framework may have conceptually "no value" at specific object life cycles.

Flip provides two way to represents this value :

One will activate one option or another using the processor macros or definitions. For example :

flip_NOTHING=flip_NOTHING_FATAL

flip_ENTITY_USE

The flip Framework Entity system allows to bind an arbitraty object to a flip Object or Type. The system itself is type safe and memory leak safe. However if one does not erase from the Entity an object it previously emplaced, there is no way for the client of the Flip framework to exactly monitor when the underlying object is going to be effectively freed.

For this reason, the Flip framework allows to detect those situation and may force the developer to erase explicitely the object to ensure it has control over the life span of the object.

Note: flip_ENTITY_USE is ignored if flip_ENTITY_LOCATION is set to flip_ENTITY_LOCATION_NONE

One will activate one option or another using the processor macros or definitions. For example :

flip_ENTITY_USE=flip_ENTITY_USE_RELAXED

flip_ENTITY_LOCATION

The flip Framework Entity system allows to bind an arbitraty object to a flip Object (or derived) or Type. While being convenient, its memory usage might be a concern if it is only used for object and never for basic types such as Int or Float, or never at all.

For this reason, the Flip framework allows either to have the entity available for any kind of Flip object, to restrict only to flip Object (that is, not any basic types), or to remove completely the feature from Flip.

Note: flip_ENTITY_USE is ignored if flip_ENTITY_LOCATION is set to flip_ENTITY_LOCATION_NONE

One will activate one option or another using the processor macros or definitions. For example :

flip_ENTITY_LOCATION=flip_ENTITY_LOCATION_OBJECT

flip_ALLOCATOR_BIND

The flip Framework is using internally an allocator to produce a unique Ref for every objects that behaves like an address in the global address space of all users/actors sharing the same document. While manipulating a document on the local machine, a mapping is done between the Ref of a flip object and the underlying Type pointer.

This binding can be slow and for this reason flip can be configured to use different binding algorithms :

flip_ALLOCATOR_BIND_MAP

flip_ALLOCATOR_BIND_MAP is the most simple and conservative algorithm. Binding and unbinding is slow since a search is done in the std::map each time.

flip_ALLOCATOR_BIND_PANDA

flip_ALLOCATOR_BIND_PANDA uses the Ref allocation properties to accelerate the default behavior, but to the disadvantage to take more memory over time.

Because Ref allocation always grows, there is more chance for a binding to happen at the end of the mapping list, and so a std::deque was used since it provides a better memory locality as neighbouring Refs are likely to be accessed when executing flip algorithms.

Because std::deque has non-constant removal time for elements that are not at the beginning or end of the sequence, unbound elements are marked as unbound but not removed from the std::deque. As a result, the std::deque will always grow when repeatitivly erasing and inserting elements.

If the memory groth is acceptable to your application and RefAllocator::bind dominates the time spent in flip when profiling your application, then you might want to use this allocator configuration.