Documentation - C API
VLFeat design concepts

VLFeat is designed to be portable and simple to integrate with high level languages such as MATLAB. This section illustrates and motivates the aspects of the design that are relevant to the users of the library.

Memory and resource handling

Some VLFeat functions return pointers to memory blocks or objects. Only vl_malloc, vl_calloc, vl_realloc, or functions whose name contains either the keywords new or copy, transfer the ownership of the memory block or object to the caller. The caller must dispose explicitly of all the resources he owns (by calling vl_free for a memory block, or the appropriate destructor for an object).

The memory allocation functions can be customized by vl_set_alloc_func (which sets the implementations of vl_malloc, vl_realloc, vl_calloc and vl_free). Remapping the memory allocation functions can be done only if there are no currently allocated VLFeat memory blocks or objects. The memory allocation functions are common to all threads.

VLFeat uses three rules that simplify handling exceptions:

  • The only resource referenced by VLFeat objects is memory (for instance, it is illegal for an object to reference an open file). Other resources such as files or threads may be allocated within a VLFeat function call, but they are all released before the function ends, or their ownership is directly transferred to the caller.
  • The global library state is an exception. It cannot reference any local object created by the caller and uses the standard C memory allocation functions.

In this way, the VLFeat local state can be reset at any time simply by disposing of all the memory allocated so far. The latter can be done easily by mapping the memory allocation functions to implementations that track the memory blocks allocated, and simply disposing of all such blocks. Since the global state does not reference any local object nor uses the remapped memory functions, it is unaffected by such an operation; conversely, since no VLFeat object references anything but memory, this guarantees that all allocated resources are properly disposed (no leaks). This is used extensively in the design of MATLAB MEX files (see MATLAB integration issues).

Objects

Many VLFeat algorithms are availale in the form of “objects”. Notice that the C language, used by VLFeat, does not support objects explicitly. Here an object indicates an opaque data structure along with a number of functions (methods) operationg on it.

Object names are captilaised and start with the Vl prefix (for example VlSiftFilt). Object methods are lowercase and start with the vl_<object_name>_ suffix (e.g. vl_sift_new). Object methods typraically include a constructor (e.g. vl_sift_new), a destructor (vl_sift_delete), some getter methods (vl_sift_get_octave_index), and some setter methods (vl_sift_set_magnif).

Multi-threading

VLFeat can be used with multiple threads by treating appropriately different kinds of operations:

  • Local operations (reentrancy). Most VLFeat operations are reentrant, in the sense that they operate on local data. It is safe to execute such operations concurrently from multiple threads as long as each thread operates on an independent sets of objects or memory blocks. By contrast, operating on the same object or memory block from multiple threads requires proper synchronization by the user.
  • Task-specific operations. A few operations are intrinsically non-reentrant but thread-specific. These include: retrieving the last error by vl_get_last_error and obtaining the thread-specific random number generator by vl_get_rand. VLFeat makes such operations thread-safe by operating on task-specific data.
  • Global operations. A small number of operations are non-reentrant and affect all threads simultaneously. These are restricted to changing certain global configuration parameters, such as the memory allocation functions by vl_set_alloc_func. These operations are not thread safe and should be executed before multiple threads are started.

Some VLFeat algorithms are randomised. Each thread has his own random number generator (an instance of VlRand) accessed by vl_get_rand. To make calculations reproducible the random number generator must be seeded appropriately in each thread. Notice also that using the same VLFeat object from multiple threads (with appropriate synchronization) will cause multiple random number generators to be intermixed.

Portability features

Platform dependent details are isolated in the host.h library module. These include:

VLFeat uses processor specific features (e.g. Intel SSE) if those are available at run time.

MATLAB integration issues

The VLFeat C library is designed to integrate seamlessly with MATLAB. Binary compatibility is simplified by the use of the C language (rather than C++). In addition, the library design follows certain restrictons that make it compatible with the MATLAB MEX interface.

The main issue in calling a library function from a MATLAB MEX function is that MATLAB can abort the execution of the MEX function at any point, either due to an error, or directly upon a user request (Ctrl-C) (empirically, however, a MEX function seems to be interruptible only during the invocation of certain functions of the MEX API such as mexErrMsgTxt).

When a MEX function is interrupted, resources (memory blocks or objects) whose ownership was transferred from VLFeat to the MEX function may be leaked. Notice that interrupting a MEX function would similarly leak any memory block allocated within the MEX function. To solve this issue, MATLAB provides his own memory manager (mxMalloc, mxRealloc, ...). When a MEX file is interrupted or ends, all memory blocks allocated by using one of such functions are released, preventing leakage.

In order to integrate VLFeat with this model in the most seamless way, VLFeat memory allocation functions (vl_malloc, vl_realloc, vl_calloc) are mapped to the corresponding MEX memory allocation functions. Such functions automatically dispose of all the memory allocated by a MEX function when the function ends (even because of an exception). Because of the restrictions of the library design illustrated in Memory and resource handling, this operation is safe and correctly dispose of VLFeat local state. As a consequence, it is possible to call mexErrMsgTxt at any point in the MEX function without worring about leaking resources.

This however comes at the price of some limitations. Beyond the restrictions illustred in Memory and resource handling, here we note that no VLFeat local resoruce (memory blocks or objects) can persist across MEX file invocations. This implies that any result produced by a VLFeat MEX function must be converted back to a MATLAB object such as a vector or a structure. In particular, there is no direct way of creating an object within a MEX file, returning it to MATLAB, and passing it again to another MEX file.

Preprocessor metaprogramming

Part of VLFeat code uses a simple form of perprocessor metaprogramming. This technique is used, similarly to C++ templates, to instantiate multiple version of a given algorithm for different data types (e.g. float and double).

In most cases preprocessor metaprogramming is invisible to the library user, as it is used only internally.