FreeElectron
Data System Primer

Design Overview

Application Considerations

The data system is designed to provide a safe robust run-time aggregate type system with high performance for common use cases.

However, lifecycle management of instances is relatively expensive due to the requirement to be safe and robust. Creation and deletion of records, even arrays at a time, can be time consuming. Therefore, it is recommended to avoid using the data system for data that is of high quantity but short lifetime.

For example a collisional particle system with maybe 10,000 particles could easily have 50,000 different collisions per frame. The collisions themselves probably should not be dealt with as records, at least not without culling first or pooling. (ProxMultiGrid is an example of pooling)

data_design.jpg

Common Tasks

Prerequisites for Use

A Scope is needed to manage a namespace of attributes.

sp<Scope> spScope(new Scope());

Creating Accessors

Accessors are the primary and recommended way of accessing Attributes within a record. Accessors are initialized for a particular Attribute within a particular Scope, after which they may be used to access the Attribute for any Record within that Scope.

Accessor<int> myAccessor;
myAccessor.setup(spScope, "myAttribute");

Create a Layout

A layout is the (type) of this aggregate type system. It is made up of Attributes. The actual Attributes of a Layout are determined when a Layout is (locked), which will happen automaticly when a record of the Layout is created. This means that disparate plugins may populate a Layout with Attributes that each plugin will need.

sp<Layout> spLayout = spScope->declare("my_layout");
spLayout->populate(myAccessor);

Create a Record

Record record_instance = spScope->createRecord(spLayout);

Check for the existence of a Attribute within a Record

if(myAccessor.check(record_instance))
{
}

data_access_techniques

Access an Attribute within a Record

myAccessor(record_instance) += 1;

Create a RecordGroup and add a Record

sp<RecordGroup> spRG(new RecordGroup);
spRG->add(record_instance);

Access an Attribute if is exists, using a default value otherwise

This is an example of trying to access an attribute within a nested record (record as an attribute of another record)

Real val = 1.0;
if(recordAccessor.check(record))
{
if(recordAccessor(record).isValid())
{
if(valueAccessor.check(recordAccessor(record)))
{
val = valueAccessor(recordAccessor(record));
}
}
}

Here is another way of doing the same thing

Real val = 1.0;
Record *pRecord = recordAccessor.queryAttribute(record);
if(pRecord && pRecord->isValid())
{
Real pValue = valueAccessor.queryAttribute(pRecord);
if(pValue)
{
val = *pValue;
}
}

However, this can be significantly cleaned up by specifiying a default value with the normal access operation

Real val = valueAccessor( recordAccessor(record, Record()) , 1.0);

But wait, there's an even easier way, the PathAccessor:

PathAccessor<Real> accessor(spScope, "recordattr.valueattr");
Real val = accessor(record, 1.0);

Iterate through a RecordGroup

Iteration of a RecordGroup is typically done by iterating through its constituent RecordArray instances, iterating through the Record instances within each RecordArray. This is done so that checking for the existance of a particular attribute may happen per Layout, not per Record instance.

for(RecordGroup::iterator it = spRG->begin(); it != spRG->end(); it++)
{
sp<RecordArray> spRA(*it);
for(int i = 0; i < spRA->length(); i++)
{
Record r = spRA->getRecord(i);
}
}