ShareEmail this to someoneShare on RedditTweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

The library has its own implementation of smart pointers. There are two types of pointers. The first type has exclusive ownership sematic an they are called auto pointers. The second one has shared ownership semantic, called smart pointers.

Exclusive ownership means that only one auto pointer is responsible for the object and control of its lifetime. When that pointer is destroyed, the wrapped object is also destroyed. It is possible to assign ownership of the object to another auto pointer, in which case the original pointer loses ownership. It is also possible to convert auto pointer to smart pointer, but not the other way around.

Shared ownership means that there can be multiple pointers that point to the object, and only after the last pointer is destroyed, the wrapped object is also destroyed. Shared sematic is implemented using reference counting, which means that circular references will cause memory leaks, so they have to be used carefully. Reference count is stored in separate object that are called storage objects.

Deletion policy defines how the objects are destroyed when they are no longer needed. In case of auto pointer, deletion policy is part of pointer. When smart pointers are used, deletion policy is part of smart storage.

Auto pointers are implemented by GaAutoPtr class. During the construction of new pointer user can specify targeted object and deletion policy. If deletion policy is not specified pointer will use GaObjectDeletionPolicy. The policy cannot be changed later, but user can specify new policy when when another object is assigned to the pointer. Specified deletion policy will be invoked by the pointer’s destructor or when new object is assigned to the pointer.

In some cases it might be required to create another instance of auto pointer that will point to the same object, to achieve this user can call MakeWeak method. It will create another pointer with no deletion policy. It is also possible to detach object from the pointer by calling DetachPointer method. Raw pointers are exposed through GetRawPtr method.

Smart pointers are implemented by GaSmartPtr class and storage objects are represented by GaSmartStorage class. Storage object owns wrapped object and manages reference count, the number of smart pointers that points to owned object, as well as deletion policy. When reference count reaches zero, deletion policy is invoked and the owned object is destroyed. It is not possible to change deletion policy once that storage object is created. AddReference and RemoveReference methods in GaSmartStorage class are called by smart pointer when its value is set. Smart pointer has to hold reference to storage object, so it can update reference count, but it also stores reference to wrapped object to improve performance. It is not possible to convert smart pointer to auto pointer. Raw pointers are exposed through GetRawPtr method.

Base class for deletion policy is GaDeletionPolicy and it has abstract operator () which is responsible for object destruction. Two default implementations of deletion policies are available in the library:

GaObjectDeletionPolicy and GaArrayDeletionPolicy. GaObjectDeletionPolicy should be used when pointer points to a single object and delete operation on the object is enough. GaArrayDeletionPolicy should to be used when pointer points to array of objects and delete[] operation on the array of objects is enough. Since all operations are idempotent, only single instance of these classes enough during the lifetime of an application, both classes has GetInstance class methods that return global instance of deletion policy. In case that it is not required to perform any actions to destroy an object, user can use GaNoDeletionPolicy.

All operations that are performed on auto/smart pointers are thread-safe.

For more details about threads see documentation of following classes:

Object Pools

To reduce allocation and freeing of the memory, as well as unnecessary object initialization and resource cleanup, library offers object pools. Pools should be used for objects that are being created and destroyed frequently.

Pool keeps set of pre-allocated objects of specified type that are already partially initialized to reduce time required to provide fully constructed objects to the user. When user tries to acquire object the pool calls procedure that completes initialization of an object, removes it from the pool and returns reference. If the pool is empty, memory is allocated and new object is constructed.

When user wants to release object and return it back to the pool, when it is no longer needed, pool preforms minimal cleanup of the resources used by the object and returns it to list of available object so user can reuse it again. If the pool is full, it will destroy object completely and release the memory.

This approach saves processor time that otherwise would be wasted on complete initialization and cleanup of objects that are unnecessary since they are soon going to be reused. To gain maximum speed, only critical resources should be freed after the object is returned to the pool.

GaObjectPool class implements object pools in the library. Four policies should be specified to the pool as template parameters:

  • CREATE_POLICY – defines how the new object is created when user tries to acquire object from empty pool.
  • DELETE_POLICY – defines how the object is destroyed when user tries to pool object back to full pool.
  • INIT_POLICY – defines how the object is initialized before it is returned when user tries to acquire it from the pool.
  • CLEAN_POLICY – defines how the object is cleaned when user wants to return it back to the pool.

The library has default policies implemented by these classes:

  • GaPoolObjectCreate – basic create policy that allocates memory and invokes object’s constructor. It is suitable for types that have constructors that do not require any parameters. (return new T();)
  • GaPoolObjectDelete – basic delete policy that invokes destructors and frees memory.
  • GaPoolObjectInit – initialization policy that does not perform any actions.
  • GaPoolObjectClean – cleanup policy that does not perform any actions.

AcquireObject, AcquireObjectWithAutoPtr and AcquireObjectWithSmartPtr methods acquire objects from the pool but returns different kind of pointers so user can make a choice depending on the needs. To return object to the pool user needs to call ReleaseObject method and provides pointer to the object. In case the object was obtained using one of the methods that return smart pointers, user does not have to call ReleaseObject method, since it will be called automatically by the deletion policy when all pointers to the object expire/go out of scope.

Since objects in the pool are partial initialized it is possible that their states become invalid, usually after performing changes on the algorithms. User can either invalidate pool and remove all objects by calling Invalidate method or update all objects by calling UpdateObjects and provide update policy. GaPoolObjectUpdate class represents interface for update policy. All update policies should use this class as a base and override operator ().

For more details about threads see documentation of following classes: