Loading...
Searching...
No Matches
persistent_table

persistent data base

# Description

Here is a convenient way to implement a persistent data base of big object that are long to initialize and then used only in a read-only mode, via accessors, no modifiers. Examples of such objects in scientific computing are are finite element meshes (see geo), that are long to load from file and requires large memory, or high-order polynomial basis (see basis), that are long to initialize (e.g. Vandermonde matrix inversion). When such objects are created independently in different parts of a code, both memory size and computation time could be save by reusing them when these objects was already created.

The aim of the persistent_table class is to automate the implementation of a persistent data base for a generic object, that could be e.g. a finite element mesh or a polynomial basis. It requires very few modification of a pre-existing object. The implementation of the persistent_table class bases on those of smart_pointer class for handling reference counting. When shared object in the data base are not modifiable, the idea is to use the smart_pointer_nocopy class. Otherwise, when the object has to be modified, the name of the object, that is used as a key in an hashtable, should also be modified, in order to address the new modified object. Here is a small minimalist example of the class.

# Example

struct A_rep {
public:
A_rep (const string& name1) : _name(name1) { /* long init */ }
~A_rep();
string name() const { return _name; }
static A_rep* make_ptr (const string& name) { return new A_rep (name); }
// data:
protected:
string _name;
};
struct A : public smart_pointer_nocopy<A_rep>, public persistent_table<A> {
public:
using rep = A_rep;
using base = smart_pointer_nocopy<rep>;
A (const string& name = "");
string name() const { return base::data().name(); }
};
// implementation of members:
A::A (const string& name)
: base(),
persistent_table<A>()
{
if (name == "") return;
base::operator= (persistent_table<A>::load (name));
}
A_rep::~A_rep()
{
persistent_table<A>::unload (_name);
}
int main() {
persistent_table<A>::set_verbose (true); // trace table load/unload
A a("a"); // "a" created
{
A b("b"); // "b" created
A c("a"); // "a" reused from table
} // "b" destroyed and erased from table
{
A b("b"); // "b" created
A c("a"); // "a" reused from table
} // "b" destroyed and erased from table
} // "a" destroyed and erased from table

# Implementation

This documentation has been generated from file util/lib/persistent_table.h

template<class A>
class persistent_table {
public:
static A load (const std::string& name);
static void unload (const std::string& name);
static bool verbose () { return _verbose; }
static void set_verbose (bool v) { _verbose = v; }
protected:
using loaded_map_type = std::unordered_map<std::string,void*>;
static loaded_map_type& get_loaded_map() { return _loaded_map; }
// data:
static loaded_map_type _loaded_map;
static bool _verbose;
};