Menu

RoomyAPI

Daniel Kunkle

Roomy API

The following lists all methods available in Roomy. There are three data structures in Roomy: RoomyArray, RoomyHashTable, and RoomyList. All methods are prefixed by the data structure they are applied to, e.g., all array methods are prefixed with RoomyArray_. General Roomy methods that are not applied to a specific data structure are prefixed with Roomy_.


RoomyArray

makeBytes

RoomyArray* RoomyArray_makeBytes(char* name, uint64 bytesPerElt, uint64 numElts)

Create a RoomyArray with numElts elements, each of size bytesPerElt bytes. The given name is used for file naming, and must be unique over all Roomy data structures.

Returns a pointer to the new RoomyArray.

Error: Returns NULL if there is another Roomy data structure with the given name.

makeBits

RoomyArray* RoomyArray_makeBits(char* name, uint64 bitsPerElt, uint64 numElts)

The same as RoomyArray_makeBytes, except the element size is specified in bits instead of bytes. The number of bits per element must be in the range 1 <= bitsPerElt <= 7.

Returns a pointer to the new RoomyArray.

Error: Returns NULL if there is another Roomy data structure with the given name. It is a fatal error if bitsPerElt is out of range.

makeFromList

RoomyArray* RoomyArray_makeFromList(char* name, RoomyList* rl)

Make a RoomyArray using the elements in the given RoomyList. The size of the new array is the same as the number of elements currently in the given list. The size of the elements of the array is the same as the size of the elements in the list.

Returns a pointer to the new RoomyArray.

Error: Returns NULL if there is another Roomy data structure with the given name.

destroy

void RoomyArray_destroy(RoomyArray* ra)

Destroys the given RoomyArray and deletes all files associated with it.

size

uint64 RoomyArray_size(RoomyArray* ra)

Returns the size of the given RoomyArray (the number of elements in the array).

map

void RoomyArray_map(RoomyArray* ra, void (*mapFunc)(uint64 i, void* val))

Given a function mapFunc to map, and a RoomyArray ra: for each index i, execute the function mapFunc(i, ra[i]). For example, the following code will add every element in a RoomyArray to a RoomyList.

RoomyArray* ra;
RoomyList* rl;

// Function to map over ra.
void mapFunc(uint64 i, void* val) {
    RoomyList_add(rl, val);
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    ra = RoomyArray_makeBytes("array", sizeof(uint64), 100);
    rl = RoomyList_make("list", sizeof(uint64));
    RoomyArray_map(ra, mapFunc);  // execute map
    RoomyList_sync(rl);  // synchronize list to complete delayed 'add' ops
    Roomy_finalize();
}

mapAndModify

void RoomyArray_mapAndModify(
    RoomyArray *ra,
    void (*mapFunc)(uint64 i, void* oldVal, void* newValOut))

Like RoomyArray_map, but also modifies the RoomyArray it is applied to. Given a function mapFunc to map, and a RoomyArray ra: for each index i, execute the function mapFunc(i, ra[i], newVal), and set ra[i] = newVal. The modification of the RoomyArray is performed during the map process and does not require RoomyArray_sync to be called to take effect.

For example, the following code sets ra[i] = 2 * i for all elements of RoomyArray ra.

RoomyArray* ra;

// Function to map over ra.
void mapFunc(uint64 i, void* oldVal, void* newVal) {
    *(uint64*)newVal = 2 * i;
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    ra = RoomyArray_makeBytes("array", sizeof(uint64), 100);
    RoomyArray_mapAndModify(ra, mapFunc);  // execute map, no need to sync
    Roomy_finalize();
}

reduce

void RoomyArray_reduce(
    RoomyArray *ra,
    void* ansInOut,
    uint64 bytesInAns,
    void (*mergeValAndAns)(void* ansInOut, uint64 i, void* val),
    void (*mergeAnsAndAns)(void* ansInOut, void* ansIn))

Collect a "reduction" of the given RoomyArray. The result, containing bytesInAns bytes, will be returned in the pointer ansInOut. The ansInOut pointer will also serve as an input for the initial (i.e. default) value for the reduction answer. The first function given, mergeValAndAns, will be used to update a partial answer given an element from the array. The second function given, mergeAnsAndAns, will be used to merge two partial answers. The order of reductions is not guaranteed, so the merge functions must be associative and commutative, or else the result is undefined.

For example, the following code returns the sum of the squares of all of the elements in a RoomyArray.

RoomyArray* ra;

// First reduction function: reduce and an array element and partial answer.
void mergeValAndAns(void* ansInOut, uint64 i, void* val) {
    uint64* ans_u64 = (uint64*)ansInOut;
    uint64* val_u64 = (uint64*)val;
    *ans_u64 = *ans_u64 + *val_u64 * *val_u64;
}

// Second reduction function: reduce two partial answers.
void mergeAnsAndAns(void* ansInOut, void* ansIn) {
    uint64* ans1_u64 = (uint64*)ansInOut;
    uint64* ans2_u64 = (uint64*)ansIn;
    *ans1_u64 = *ans1_u64 + *ans2_u64;
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    ra = RoomyArray_makeBytes("array", sizeof(uint64), 100);
    // ... code that initializes ra ...
    uint64 sum = 0;
    RoomyArray_reduce(ra, &sum, sizeof(uint64), mergeValAndAns, mergeAnsAndAns);
    Roomy_finalize();
}

registerAccessFunc

void RoomyArray_registerAccessFunc(RoomyArray* ra,
    void (*accessFunc)(uint64 i, void* arrayVal, void* passedVal),
    uint64 passedValSize)

Register an access function for later use with RoomyArray_access. After registering, the function accessFunc can be used on RoomyArray ra. The value passed to RoomyArray_access will contain passedValSize bytes. See the documentation for RoomyArray_access for an example.

access

void RoomyArray_access(RoomyArray *ra, uint64 i, void* passedVal,
    void (*accessFunc)(uint64 i, void* arrayVal, void* passedVal))

NOTE: this is a delayed operation. You must call RoomyArray_sync for this operation to take effect.

Access index i of RoomyArray ra. The given access function will be executed as: accessFunc(i, ra[i], passedVal).

The access function accessFunc must have been previously registered with ra using RoomyArray_registerAccessFunc. It is a fatal error if it was not.

As an example, the following code accesses an element of a RoomyArray and prints the value to stdout using Roomy_log.

RoomyArray* ra;

// Function to print an element.
void accessFunc(uint64 i, void* arrayVal, void* passedVal) {
    Roomy_log("ra[%lli] = %lli\n", i, *(uint64*)arrayVal);
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    ra = RoomyArray_makeBytes("array", sizeof(uint64), 100);
    // no passed value, so passedValSize is zero and passedVal is NULL
    RoomyArray_registerAccessFunc(ra, accessFunc, 0);
    RoomyArray_access(ra, 42, NULL, accessFunc);
    RoomyArray_sync(ra);  // synchronize to complete delayed access
    Roomy_finalize();
}

registerUpdateFunc

void RoomyArray_registerUpdateFunc(
    RoomyArray* ra,
    void (*updateFunc)(uint64 i, void* oldVal, void* updateVal, void* newValOut),
    uint64 updateValSize)

Register an update function for later use with RoomyArray_update. After registering, the function updateFunc can be used on RoomyArray ra. The update value passed to RoomyArray_update will contain updateValSize bytes. See the documentation for RoomyArray_update for an example.

update

void RoomyArray_update(RoomyArray *ra, uint64 i, void* updateVal,
    void (*updateFunc)(uint64 i, void* oldVal, void* updateVal, void* newValOut))

NOTE: this is a delayed operation. You must call RoomyArray_sync for this operation to take effect.

Update index i of RoomyArray ra using the given update value and update function. In other words: ra[i] = updateFunc(i, ra[i], updateVal), where newValOut is the result to be stored in ra[i].

The update function updateFunc must have been previously registered with ra using RoomyArray_registerUpdateFunc. It is a fatal error if it was not.

As an example, the following code updates an element of a RoomyArray by adding a given number to it.

RoomyArray* ra;

// Update function to add a number to an element.
void updateFunc(uint64 i, void* oldVal, void* updateVal, void* newValOut) {
    *(uint64*)newValOut = *(uint64*)oldVal + *(uint64*)updateVal;
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    ra = RoomyArray_makeBytes("array", sizeof(uint64), 100);
    RoomyArray_registerUpdateFunc(ra, updateFunc, sizeof(uint64));
    uint64 updateVal = 12345;
    RoomyArray_update(ra, 42, &updateVal, updateFunc);
    RoomyArray_sync(ra);  // synchronize to complete delayed update
    Roomy_finalize();
}

attachPredicate

void RoomyArray_attachPredicate(RoomyArray* ra,
                                uint8 (*predFunc)(uint64 i, void* val))

A predicate is a function that is applied to every element of a Roomy data structure, and returns 0 or 1 for each element. RoomyArray_attachPredicate attaches the predicate predFunc to RoomyArray ra. All further updates to ra will be processed by the predicate function, and a total count of the number of elements satisfying the predicate is kept.

To ensure the count is accurate, the predicate function must be attached to the RoomyArray just after construction, and must return 0 for a zeroed array element.

Note that the same thing could be achieved using RoomyArray_reduce, but using a predicate function is more efficient because it does not require an additional scan of the array.

See RoomyArray_predicateCount to see how to access the current number of elements satisfying a predicate, and for example code.

predicateCount

uint64 RoomyArray_predicateCount(RoomyArray* ra,
                                 uint8 (*predFunc)(uint64 i, void* val))

Returns the number of elements in the RoomyArray ra that satisfy the predicate function predFunc.

The predicate function must have been previously attached to ra using RoomyArray_attachPredicate. It is a fatal error if it was not.

As an example, the following is a predicate to count the number of non-zero elements in a RoomyArray.

RoomyArray* ra;

// Predicate function returning 1 if element is non-zero.
uint8 predFunc(uint64 i, void* arrayVal) {
    return *(uint64*)arrayVal != 0;
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    ra = RoomyArray_makeBytes("array", sizeof(uint64), 100);
    RoomyArray_attachPredicate(ra, predFunc);
    // ... code that modifies ra ...
    uint64 numNonZero = RoomyArray_predicateCount(ra, predFunc);
    Roomy_finalize();
}

sync

void RoomyArray_sync(RoomyArray* ra)

Process all outstanding delayed operations for the RoomyArray ra. Delayed operations include RoomyArray_update and RoomyArray_access.

There is no guarantee of the order in which delayed operations are processed. If you need to preserve the ordering of delayed operations, you can perform the first set of operations, synchronize, then perform the second set of operations.

If processing outstanding delayed operations creates additional delayed operations, those new delayed operations will not be performed until the next synchronization.

isSynced

int RoomyArray_isSynced(RoomyArray* ra)

Return 1 if the RoomyArray ra is synchronized (has no outstanding delayed operations). Return 0 otherwise.


RoomyHashTable

make

RoomyHashTable* RoomyHashTable_make(char* name, int keySize, int valueSize,
                                    uint64 capacity)

Create a RoomyHashTable with keys containing keySize bytes and values containing valueSize bytes. The given name is used for file naming, and must be unique over all Roomy data structures.

The table is initially sized to have room for at least capacity entries. If the number of unique entries inserted exceeds the current capacity, the capacity will be increased. Because this processes of expansion can negatively impact performance, it is best to provide an accurate capacity when making the RoomyHashTable.

Returns a pointer to the new RoomyHashTable.

Error: Returns NULL if there is another Roomy data structure with the given name.

destroy

void RoomyHashTable_destroy(RoomyHashTable* rht)

Destroys the given RoomyHashTable and deletes all files associated with it.

size

uint64 RoomyHashTable_size(RoomyHashTable* rht)

Returns the number of elements contained in the given RoomyHashTable.

map

void RoomyHashTable_map(RoomyHashTable* rht,
                        void (*mapFunc)(void* key, void* value))

Given a function mapFunc to map, and a RoomyHashTable rht: for each key/value pair (key, value), execute the function mapFunc(key, value).

For example, the following code will create the reverse of a RoomyHashTable: another RoomyHashTable with keys and values reversed.

RoomyHashTable* forward;
RoomyHashTable* reverse;

// Function to map over forward.
void mapFunc(void* key, void* value) {
    RoomyHashTable_insert(reverse, value, key);
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    forward = RoomyHashTable_make("forward", keySize, valueSize, capacity);
    reverse = RoomyHashTable_make("reverse", valueSize, keySize, capacity);
    // ... code to initialize forward table...
    RoomyHashTable_map(forward, mapFunc);  // execute map
    RoomyHashTable_sync(reverse);  // sync to complete delayed 'insert' ops
    Roomy_finalize();
}

reduce

void RoomyHashTable_reduce(
  RoomyHashTable *rht,
  void* ansInOut,
  uint64 bytesInAns,
  void (*mergeValAndAns)(void* ansInOut, void* key, void* value),
  void (*mergeAnsAndAns)(void* ansInOut, void* ansIn))

Collect a "reduction" of the given RoomyHashTable. The result, containing bytesInAns bytes, will be returned in the pointer ansInOut. The ansInOut pointer will also serve as an input for the initial (i.e. default) value for the reduction answer. The first function given, mergeValAndAns, will be used to update a partial answer given a key/value pair from the hash table. The second function given, mergeAnsAndAns, will be used to merge two partial answers. The order of reductions is not guaranteed, so the merge functions must be associative and commutative, or else the result is undefined.

For example, the following code returns the sum of all of the values that have an even-numbered key.

RoomyHashTable* rht;

// First reduction function: reduce and a key/value pair and partial answer.
void mergeValAndAns(void* ansInOut, void* key, void* val) {
    uint64* ans_u64 = (uint64*)ansInOut;
    uint64* key_u64 = (uint64*)key;
    uint64* val_u64 = (uint64*)val;
    if (*key_u64 % 2 == 0) {
        *ans_u64 = *ans_u64 + *val_u64;
    }
}

// Second reduction function: reduce two partial answers.
void mergeAnsAndAns(void* ansInOut, void* ansIn) {
    uint64* ans1_u64 = (uint64*)ansInOut;
    uint64* ans2_u64 = (uint64*)ansIn;
    *ans1_u64 = *ans1_u64 + *ans2_u64;
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    rht = RoomyHashTable_make("table", sizeof(uint64), sizeof(uint64), capacity);
    // ... code that inserts elements in rht ...
    uint64 sum = 0;
    RoomyHashTable_reduce(
        rht, &sum, sizeof(uint64), mergeValAndAns, mergeAnsAndAns);
    Roomy_finalize();
}

registerAccessFunc

void RoomyHashTable_registerAccessFunc(
  RoomyHashTable* rht,
  void (*accessFunc)(void* key, void* tableValue, void* passedValue),
  uint64 passedValSize)

Register an access function for later use with RoomyHashTable_access. After registering, the function accessFunc can be used on RoomyHashTable rht. The value passed to RoomyHashTable_access will contain passedValSize bytes. See the documentation for RoomyHashTable_access for an example.

access

void RoomyHashTable_access(
  RoomyHashTable* rht, void* key, void* passedValue,
  void (*accessFunc)(void* key, void* tableValue, void* passedValue))

NOTE: this is a delayed operation. You must call RoomyHashTable_sync for this operation to take effect.

Access the key/value pair with they given key. The given access function will be executed as: accessFunc(key, tableValue, passedVal). If no value is associated with the given key, tableValue will be NULL.

The access function accessFunc must have been previously registered with rht using RoomyHashTable_registerAccessFunc. It is a fatal error if it was not.

As an example, the following code accesses an element of a RoomyHashTable and prints the key/value pair to stdout using Roomy_log.

RoomyHashTable * rht;

// Function to print an element.
void accessFunc(void* key, void* tableValue, void* passedVal) {
    Roomy_log("rht[%lli] = %lli\n", *(uint64*)key, *(uint64*)tableVal);
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    rht = RoomyHashTable_make("table", sizeof(uint64), sizeof(uint64), capacity);
    // no passed value, so passedValSize is zero and passedVal is NULL
    RoomyHashTable_registerAccessFunc(ra, accessFunc, 0);
    uint64 key = 42;
    RoomyHashTable_access(rht, &key, NULL, accessFunc);
    RoomyHashTable_sync(rht);  // synchronize to complete delayed access
    Roomy_finalize();
}

registerUpdateFunc

void RoomyHashTable_registerUpdateFunc(
  RoomyHashTable* rht,
  void (*updateFunc)(void* key, void* oldValue, void* passedValue, void* newValOut),
  uint64 passedValSize)

Register an update function for later use with RoomyHashTable_update. After registering, the function updateFunc can be used on RoomyHashTable rht. The value passed to RoomyHashTable_update will contain passedValSize bytes. See the documentation for RoomyHashTable_update for an example.

update

void RoomyHashTable_update(
  RoomyHashTable* rht, void* key, void* passedValue,
  void (*updateFunc)
    (void* key, void* oldValue, void* passedValue, void* newValOut))

NOTE: this is a delayed operation. You must call RoomyHashTable_sync for this operation to take effect.

Update the key/value pair with the given key in RoomyHashTable rht using the given passed value and update function. In other words: rht[key] = updateFunc(key, rht[key], passedVal), where newValOut is the result to be stored in rht[key].

If there is no value associated with the given key, oldValue will be NULL, and a new key/value pair will be inserted with the new value.

The update function updateFunc must have been previously registered with rht using RoomyHashTable_registerUpdateFunc. It is a fatal error if it was not.

As an example, the following code updates a key/value pair in a RoomyHashTable by adding a given number to the value. If the given key does not appear in the table, a new key/value pair is inserted.

RoomyHashTable* rht;

// Update function to add a number to a value.
void updateFunc(void* key, void* oldVal, void* passedVal, void* newValOut) {
    if (oldVal != NULL) {
        *(uint64*)newValOut = *(uint64*)oldVal + *(uint64*)passedVal;
    } else {
        *(uint64*)newValOut = *(uint64*)passedVal;
    }
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    rht = RoomyHashTable_make("table", sizeof(uint64), sizeof(uint64), capacity);
    RoomyHashTable_registerUpdateFunc(rht, updateFunc, sizeof(uint64));
    uint64 key = 42;
    uint64 updateVal = 12345;
    RoomyHashTable_update(rht, &key, &updateVal, updateFunc);
    RoomyHashTable_sync(rht);  // synchronize to complete delayed update
    Roomy_finalize();
}

insert

void RoomyHashTable_insert(RoomyHashTable* rht, void* key, void* value)

NOTE: this is a delayed operation. You must call RoomyHashTable_sync for this operation to take effect.

Insert the given key/value pair into the RoomyHashTable rht. If the key already exists, its value is replaced.

remove

void RoomyHashTable_remove(RoomyHashTable* rht, void* key)

NOTE: this is a delayed operation. You must call RoomyHashTable_sync for this operation to take effect.

Remove the key/value pair with the given key from the RoomyHashTable rht. There is no effect if the key does not exist in the table.

attachPredicate

void RoomyHashTable_attachPredicate(RoomyHashTable* rht,
                                    uint8 (*predFunc)(void* key, void* value))

A predicate is a function that is applied to every element of a Roomy data structure, and returns 0 or 1 for each element. RoomyHashTable_attachPredicate attaches the predicate predFunc to RoomyHashTable rht. All further updates to rht will be processed by the predicate function, and a total count of the number of elements satisfying the predicate is kept.

To ensure the count is accurate, the predicate function must be attached to the RoomyHashTable just after construction, and must return 0 for a zeroed element.

Note that the same thing could be achieved using RoomyHashTable_reduce, but using a predicate function is more efficient because it does not require an additional scan of the array.

See RoomyHashTable_predicateCount to see how to access the current number of elements satisfying a predicate, and for example code.

predicateCount

uint64 RoomyHashTable_predicateCount(RoomyHashTable* rht,
                                     uint8 (*predFunc)(void* key, void* value))

Returns the number of elements in the RoomyHashTable rht that satisfy the predicate function predFunc.

The predicate function must have been previously attached to rht using RoomyHashTable_attachPredicate. It is a fatal error if it was not.

As an example, the following is a predicate to count the number of elements that have key == value.

RoomyHashTable* rht;

// Predicate function returning 1 if key is equal to value
uint8 predFunc(void* key, void* value) {
    if (*(uint64*)key == *(uint64*)value) {
        return 1;
    } else {
        return 0;
    }
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    rht = RoomyHashTable_make("table", sizeof(uint64), sizeof(uint64), capacity);
    RoomyHashTable_attachPredicate(rht, predFunc);
    // ... code that modifies rht ...
    uint64 numEqual = RoomyHashTable_predicateCount(rht, predFunc);
    Roomy_finalize();
}

sync

void RoomyHashTable_sync(RoomyHashTable* rht)

Process all outstanding delayed operations for the RoomyHashTable rht. Delayed operations include RoomyHashTable_access, RoomyHashTable_update, RoomyHashTable_insert, and RoomyHashTable_remove.

There is no guarantee of the order in which delayed operations are processed. If you need to preserve the ordering of delayed operations, you can perform the first set of operations, synchronize, then perform the second set of operations.

If processing outstanding delayed operations creates additional delayed operations, those new delayed operations will not be performed until the next synchronization.

isSynced

int RoomyHashTable_isSynced(RoomyHashTable* rht)

Return 1 if the RoomyHashTable rht is synchronized (has no outstanding delayed operations). Return 0 otherwise.


RoomyList

make

RoomyList* RoomyList_make(char* name, uint64 bytesPerElt)

Create a RoomyList with elements of size bytesPerElt bytes. The given name is used for file naming, and must be unique over all Roomy data structures.

Returns a pointer to the new RoomyList.

Error: Returns NULL if there is another Roomy data structure with the given name.

makeWithKey

RoomyList* RoomyList_makeWithKey(char* name, uint64 bytesPerElt, uint64 keyStart,
                                 uint64 keySize)

The same as RoomyList_make, except element equality is determined by the keySize bytes that begin with byte keyStart. The functions that depend on element equality are RoomyList_remove, RoomyList_removeAll, and RoomyList_removeDupes.

Returns a pointer to the new RoomyList.

Error: Returns NULL if there is another Roomy data structure with the given name.

destroy

void RoomyList_destroy(RoomyList* rl)

Destroys the given RoomyList and deletes all files associated with it.

add

void RoomyList_add(RoomyList* rl, void* elt)

NOTE: this is a delayed operation. You must call RoomyArray_sync for this operation to take effect.

Add the given element to the RoomyList rl.

remove

void RoomyList_remove(RoomyList* rl, void* elt)

NOTE: this is a delayed operation. You must call RoomyArray_sync for this operation to take effect.

Remove all occurrences of the given element from the RoomyList rl.

map

void RoomyList_map(RoomyList* rl, void (*mapFunc)(void* val))

Given a function mapFunc to map, and a RoomyList rl: for each element val in the list, execute the function mapFunc(val).

mapAndModify

void RoomyList_mapAndModify(RoomyList *rl,
                     void (*mapFunc)(void* oldVal, void* newValOut))

Given a function mapFunc to map, and a RoomyList rl: for each element val in the list, execute the function mapFunc(val). After the map function is applied to a value, the value stored in newValOut will replace that value.

For example, the following code will add 1 to every element in a RoomyList.

RoomyList* rl;

// Function to map over rl.
void mapFunc(void* oldVal, void* newVal) {
    *(uint64*)newVal = *(uint64*)oldVal + 1;
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    rl = RoomyList_make("list", sizeof(uint64));
    // ... code to populate rl ...
    RoomyList_mapAndModify(rl, mapFunc);
    Roomy_finalize();
}

reduce

void RoomyList_reduce(RoomyList *rl,
                   void* ansInOut,
                   uint64 bytesInAns,
                   void (*mergeValAndAns)(void* ansInOut, void* val),
                   void (*mergeAnsAndAns)(void* ansInOut, void* ansIn))

Collect a "reduction" of the given RoomyList. The result, containing bytesInAns bytes, will be returned in the pointer ansInOut. The ansInOut pointer will also serve as an input for the initial (i.e. default) value for the reduction answer. The first function given, mergeValAndAns, will be used to update a partial answer given an element from the list. The second function given, mergeAnsAndAns, will be used to merge two partial answers. The order of reductions is not guaranteed, so the merge functions must be associative and commutative, or else the result is undefined.

For example, the following code returns both the sum and product of the elements in a RoomyList, using a single reduction.

RoomyList* rl;

// First reduction function: reduce and a list element and partial answer.
void mergeValAndAns(void* ansInOut, void* val) {
    uint64* ans = (uint64*) ansInOut;
    uint64 v = *(uint64*)val;
    ans[0] = ans[0] + v;
    ans[1] = ans[1] * v;
}

// Second reduction function: reduce two partial answers.
void mergeAnsAndAns(void* ansInOut, void* ansIn) {
    uint64* ansO = (uint64*) ansInOut;
    uint64* ansI = (uint64*) ansIn;
    ansO[0] = ansO[0] + ansI[0];
    ansO[1] = ansO[1] * ansI[1];
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    rl = RoomyList_make("list", sizeof(uint64));
    // ... code that initializes rl ...
    uint64 ans[2] = {0, 0};  // {sum, product}
    RoomyList_reduce(rl, ans, 2 * sizeof(uint64), mergeValAndAns, mergeAnsAndAns);
    Roomy_finalize();
}

attachPredicate

void RoomyList_attachPredicate(RoomyList* rl, uint8 (*predFunc)(void* val))

A predicate is a function that is applied to every element of a Roomy data structure, and returns 0 or 1 for each element. RoomyList_attachPredicate attaches the predicate predFunc to RoomyList rl. All further updates to rl will be processed by the predicate function, and a total count of the number of elements satisfying the predicate is kept.

To ensure the count is accurate, the predicate function must be attached to the RoomyList just after construction.

Note that the same thing could be achieved using RoomyList_reduce, but using a predicate function is more efficient because it does not require an additional scan of the list.

See RoomyList_predicateCount for how to access the current number of elements satisfying a predicate, and for example code.

predicateCount

uint64 RoomyList_predicateCount(RoomyList* rl, uint8 (*predFunc)(void* val))

Returns the number of elements in the RoomyList rl that satisfy the predicate function predFunc.

The predicate function must have been previously attached to rl using RoomyList_attachPredicate. It is a fatal error if it was not.

As an example, the following is a predicate to count the number of elements greater than 42 in a RoomyList.

RoomyList* rl;

// Predicate function returning 1 if element is greater than 42.
uint8 predFunc(void* val) {
    if (*(uint64*)val > 42) {
        return 1;
    } else {
        return 0;
    }
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    rl = RoomyList_make("list", sizeof(uint64));
    RoomyList_attachPredicate(rl, predFunc);
    // ... code that modifies rl ...
    uint64 numGreaterThan42 = RoomyList_predicateCount(rl, predFunc);
    Roomy_finalize();
}

size

uint64 RoomyList_size(RoomyList* rl)

Returns the number of elements contained in the given RoomyList.

removeDupes

void RoomyList_removeDupes(RoomyList* rl)

Remove all duplicate elements from the given RoomyList.

addAll

void RoomyList_addAll(RoomyList* rl1, RoomyList* rl2)

Add all elements in rl2 to rl1.

removeAll

void RoomyList_removeAll(RoomyList* rl1, RoomyList* rl2)

NOTE: this is a delayed operation. You must call RoomyList_sync for this operation to take effect.

Remove all elements in rl2 from rl1.

sync

void RoomyList_sync(RoomyList* rl)

Process all outstanding delayed operations for the RoomyList rl. Delayed operations include RoomyList_add, RoomyList_remove, and RoomyList_removeAll.

There is no guarantee of the order in which delayed operations are processed. If you need to preserve the ordering of delayed operations, you can perform the first set of operations, synchronize, then perform the second set of operations.

If processing outstanding delayed operations creates additional delayed operations, those new delayed operations will not be performed until the next synchronization.

isSynced

int RoomyList_isSynced(RoomyList* rl);

Return 1 if the RoomyList rl is synchronized (has no outstanding delayed operations). Return 0 otherwise.


Other Roomy Methods

uniqueInt

uint64 Roomy_uniqueInt()

Return a unique integer. It is unique over all compute nodes, since Roomy_init(), or the last call to Roomy_resetUniqueInt(). It can be called from both parallel and serial modes. It is very useful for assigning unique identifiers in parallel to states or pieces of data.

resetUniqueInt

void Roomy_resetUniqueInt(uint64 min)

After a call to Roomy_resetUniqueInt(uint64 min), all subsequent calls to Roomy_uniqueInt() will return unique positive integers larger than or equal to min.

log

void Roomy_log(char* message, ...)

Print a message, formatted as in printf. The message is only printed by the master Roomy process. Because of this, it should only be used outside of methods passed to Roomy (e.g., it should not be used in a method passed to RoomyArray_map).

See Roomy_logAny for an example printing messages both inside and outside of Roomy methods.

logAny

void Roomy_logAny(char* message, ...)

Print a message, formatted as in printf. The message is printed by any Roomy process, and so can be used inside of methods passed to Roomy.

The ordering of the output from the different Roomy processes is not guaranteed.

For example, the following code uses both Roomy_log and Roomy_logAny.

RoomyArray* ra;

// Print an element of a RoomyArray
void printElt(uint64 i, void* arrayVal) {
    Roomy_logAny("ra[%lli] = %lli\n", i, *(uint64*)arrayVal);
}

int main(int argc, char **argv) {
    Roomy_init(&argc, &argv);
    uint64 arraySize = 100;
    ra = RoomyArray_makeBytes("array", sizeof(uint64), arraySize);
    Roomy_log("Printing the %lli elements of ra\n", arraySize);
    RoomyArray_map(ra, printElt);
    Roomy_finalize();
}

This code would produce a result similar to the following. For Roomy_logAny, each message is labeled with the unique rank of the Roomy processes that produced the message. Messages produced by Roomy_log are only printed by rank 0.

Thu Dec 10 03:08:01 2009: Printing the 100 elements of ra
Thu Dec 10 03:08:01 2009 [rank 2]: ra[2] = 0
Thu Dec 10 03:08:01 2009 [rank 0]: ra[0] = 0
Thu Dec 10 03:08:01 2009 [rank 1]: ra[1] = 0
Thu Dec 10 03:08:01 2009 [rank 0]: ra[3] = 0
...

init

void Roomy_init(int* argc, char*** argv)

Initialize Roomy. This method muse be called before any other Roomy methods.

Roomy itself does not use any command line arguments, but those arguments are passed on to MPI_init. See the documentation for the version of MPI you are using for a list of command line arguments it accepts.

finalize

void Roomy_finalize()

Must be called at the end of the Roomy program.


Related

Wiki: Home

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.