ss_pers_t *
ss_pers_new(ss_scope_t *scope, /* The scope that will own this new object. */
unsigned tableid, /* A magic number whose sequence part defines a table */
const ss_persobj_t *init, /* Optional initial data of type ss_persobj_t or a type derived therefrom. The type must
* be appropriate for the class of object being created. This argument can be used to
* copy a persistent object. ISSUE: Should this be a link instead? */
unsigned flags, /* Creation flags, like SS_ALLSAME */
ss_pers_t *buf, /* Optional buffer for return value */
ss_prop_t UNUSED *props /* Additional properties (none defined yet) */
)
{
SS_ENTER(ss_pers_new, ss_pers_tP);
ss_persobj_t *persobj = NULL;
ss_pers_t *objlink = NULL;
size_t idxtype;
ss_table_t *table=NULL;
ss_pers_class_t *pc=NULL;
tableid = SS_MAGIC_SEQUENCE(tableid);
if (NULL==(pc=SS_PERS_CLASS(tableid))) SS_ERROR(NOTFOUND);
/* Obtain a pointer to the table for this object. */
if (NULL==(table = ss_scope_table(scope, tableid, NULL))) SS_ERROR(FAILED);
/* Obtain memory for the object and initialize it. When declaring a single new object with SS_ALLSAME we can
* immediately give it a permanent home, evicting any temporary object that might be there, because we know all tasks have
* the same number of permanent objects. */
idxtype = flags & SS_ALLSAME ? 0 : SS_TABLE_INDIRECT;
if (NULL==(persobj=ss_table_newobj(table, idxtype, init, NULL))) SS_ERROR(FAILED);
persobj->dirty = TRUE;
/* If an initial value was supplied then we may have to reallocate some of the resources in the new object so that they're
* not shared between the new object and the initial object. We do this in place (hence the NULL first argument). */
if (init && ss_val_copy(NULL, persobj, pc->valinfo_nused, pc->valinfo)<0) SS_ERROR(FAILED);
/* If all tasks are supplying the same data then mark the object as synchronized because it will save us some work when we
* actually do attempt to synchronize later. We mark it with SS_ALLSAME (which is true but distinct from the constant
* `TRUE') to indicate that we never actually synchronized but rather we just "know" that the object is in a synchronized
* state. It's not possible to avoid this little complication because the rule is that all synchronized objects have a
* last-synchronized checksum stored with them but we can't compute the checksum yet because we're just now creating an
* empty object that the user will fill in shortly. See also ss_table_synchronize(). */
if (flags & SS_ALLSAME) {
persobj->synced = SS_ALLSAME;
}
/* Create a link to the object. This will be our return value */
if (NULL==(objlink=ss_pers_refer(scope, persobj, buf))) SS_ERROR(FAILED);
SS_CLEANUP:
SS_LEAVE(objlink);
}