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* 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
.
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.
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
.
void RoomyArray_destroy(RoomyArray* ra)
Destroys the given RoomyArray
and deletes all files associated with it.
uint64 RoomyArray_size(RoomyArray* ra)
Returns the size of the given RoomyArray
(the number of elements in the array).
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(); }
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(); }
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(); }
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.
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(); }
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.
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(); }
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.
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(); }
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.
int RoomyArray_isSynced(RoomyArray* ra)
Return 1
if the RoomyArray
ra
is synchronized (has no outstanding delayed operations). Return 0
otherwise.
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
.
void RoomyHashTable_destroy(RoomyHashTable* rht)
Destroys the given RoomyHashTable
and deletes all files associated with it.
uint64 RoomyHashTable_size(RoomyHashTable* rht)
Returns the number of elements contained in the given RoomyHashTable
.
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(); }
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(); }
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.
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(); }
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.
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(); }
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.
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.
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.
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(); }
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.
int RoomyHashTable_isSynced(RoomyHashTable* rht)
Return 1
if the RoomyHashTable
rht
is synchronized (has no outstanding delayed operations). Return 0
otherwise.
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
.
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
.
void RoomyList_destroy(RoomyList* rl)
Destroys the given RoomyList
and deletes all files associated with it.
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
.
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
.
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)
.
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(); }
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(); }
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.
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(); }
uint64 RoomyList_size(RoomyList* rl)
Returns the number of elements contained in the given RoomyList
.
void RoomyList_removeDupes(RoomyList* rl)
Remove all duplicate elements from the given RoomyList
.
void RoomyList_addAll(RoomyList* rl1, RoomyList* rl2)
Add all elements in rl2
to rl1
.
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
.
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.
int RoomyList_isSynced(RoomyList* rl);
Return 1
if the RoomyList
rl
is synchronized (has no outstanding delayed operations). Return 0
otherwise.
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.
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.
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.
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 ...
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.
void Roomy_finalize()
Must be called at the end of the Roomy program.