Associations are more general than containers because, in containers, one class controls (or contains)objects of another class. This implies uni-directional control flow. Associations support cooperation between two or more classes, where all the participating classes can be actively involved.

Associations support libraries which can include not only commonly used containers, but also design patterns, intrusive data structures, graphs, many-to-many and other important data structures missing in the existing class libraries. When you use associations, you get a natural one-to-one match between your data structures and the UML model.

References: IN_CODE modelling, DOL, and PTL are completely based on the association model.

 

Intrusive data structures are safer than containers because when using rings of pointers, a simple check whether a pointer is NULL can prevent, in run time, corruption of the data structure. This protection is more effective than the tauted protection against pointer errors in Java.

Intrusive data structures are natural sets while containers are natural bags. In applications where a set is required (at most one copy of the object in a collection), intrusive data avoid expensive searches.

References: Book "Taming C++", by Jiri Soukup. In addition to full type protection, IN_CODE modelling, DOL, and PTL libraries extensively use this protection.

 

A major problem of the existing UML modelling is that the graphical model is not completely integrated with the code. The code generators are clumsy and, as the software evolves, the model and the code often does not match any more. In situations like this, a partial match is often worse (because it may be misleading) than not having any model at all.

When you work with associations, the entire data structure can be controlled by a small block of statements which describe the data organization like a database schema. This small and human-readable block of code also describes the UML logic and can be automatically converted into the UML class diagram.

Instead of trying to control the code by the diagram or the diagram by the code, we place the control between them: The textual schema controls the data structures and also generates the UML diagram. When you want to edit the UML diagram, you do not edit its picture, you edit its textual representation. It is faster and more concise.

References: Book "The next Software revolution", by Jiri Soukup. This idea is the backbone of IN_CODE modelling.

 

Memory blasting is a method of saving C++ data structures to disk which is typically 10x faster than commonly used serialization. The idea is to overload the new() operator in such a way, that all objects are allocated from the controlled pages of memory. A small part (exactly 1/32) of the page is used as a bitmap which records, already at the allocation time and for each 4-byte location, whether the location contains a pointer.

When saving data to disk, entire pages are copied to disk without any modification. When restoring data to memory, the pages are copied back to the memory, the algorithm walks through the bitmap, and when it finds 1, it converts (swizzles) the pointer. The great advantage of this scheme is that when the page size is power of 2, for example 64 or 4096, the pointer conversion does not require any search or hashing - three arithmetic operations find the new value of the pointer.

The method is so fast because the disk saving/restoring are not fragmented into individual objects, and neither is their allocation or destruction.

References: The details of the algorithm including the conversion of the internal pointers is described in "Taming C++", by Jiri Soukup. Memory blasting is one of the disk saving options in DOL, and all its code is in file lib/blast.cc.

 

Another way to make C++ object automatically and trasparently persistent is to replace all your pointers by smart pointers which make your objects persistent. The smart pointer overloads operator new() and operator -> in such a way that objects of each class are allocated from a file and not from memory, one file for each object type. The smart pointer stores the index of the object in the file (same size as the pointer, only 4 bytes) and when the object is needed, it is paged from disk to memory. The size of the page and the number of pages in memory is controlled by the user on a per-class basis.

This is an ideal arrangement for large data sets when only a small subset is needed at any given time - in warehouse operation, airline reservations, and similar applications.

When virtual functions are used, the internal virtual function pointers must be initialized only when the object is loaded for the first time within the given run. Also, when virtual functions are used, the smart pointer must store two integers, not just one. This is a lean and efficient program. The executable is only about 55kB.

References: This is the persistency used in PPF. From file factory.h which comes with the free version of PPF, you can see how to overload the operators. The full source is in factory.cpp (2k lines including comments).

 

You can view structural design patterns as data structures which, beside pointers, references and arrays also include inheritance. As such they can be stored in a library, together with other associations, data structures and containers.

References: Both PTL and IN_CODE libraries include examples of design patterns such as Composite, Flyweight, or Finite State Machine. Also see "Implementing Patterns" in the 1995 Pattern Languages of Program Design, edited by Coplien & Schmidt, p.395.