ss_pers_t *
saf_allgather_handles(ss_pers_t *_pers, /* A Pointer to the handle to be exchanged. Every participant must supply a valid
* handle of the same type and in the same scope as every other participant. */
int *commsize, /* [OUT] A pointer to optional caller supplied memory which is to receive the integer
* number of handles returned by this function. This is the number of participants or
* the size of the communicator associated with the given database. */
ss_pers_t *result /* [OUT] An optional pointer to an array that will will be initialized with a handle
* from each MPI task in task rank order. If this buffer is supplied then it should be
* at least as large as the communicator associated with the DB argument. If not
* supplied (i.e., null) then a buffer will be allocated for the return value. */
)
{
SAF_ENTER(saf_allgather_handles, NULL);
ss_scope_t scope=SS_SCOPE_NULL;
ss_file_t file=SS_FILE_NULL;
int self, ntasks=0;
size_t encoded_nused=0, encoded_nalloc=0, consumed;
char *encoded=NULL, *all_encoded=NULL;
MPI_Comm comm=SS_COMM_NULL;
/* It might be possible that the ss_pers_t pointer _PERS is a pointer into some object. If that object is a new object
* then the ss_file_synchronize() call below may clobber that memory. Therefore we copy the link onto the stack first. */
ss_pers_t pers=*_pers;
SAF_REQUIRE(ss_pers_deref(&pers), SAF_LOW_CHK_COST, NULL, _saf_errmsg("_PERS must be a valid object link"));
/* Obtain communicator info. */
ss_pers_scope(&pers, &scope);
ss_scope_comm(&scope, &comm, &self, &ntasks);
if (commsize) *commsize = ntasks;
/* Synchronize the table, thus turning the _PERS arguments into global objects. */
ss_pers_file(&pers, &file);
if (ss_file_synchronize(&file, NULL)<0)
SAF_ERROR(NULL, _saf_errmsg("file synchronization failed"));
/* Each task encodes its _PERS argument. They should all be the same size when encoded. */
encoded = ss_pers_encode_cb(&pers, NULL, &encoded_nused, &encoded_nalloc, sizeof(pers), 1);
/* Gather all the encoded object links */
all_encoded = malloc(ntasks*encoded_nused);
memcpy(all_encoded+self*encoded_nused, encoded, encoded_nused);
ss_mpi_allgather(all_encoded, encoded_nused, MPI_BYTE, comm);
/* Decode the object links into the result buffer. */
if (!result) result = malloc(ntasks*sizeof(*result));
consumed = ss_pers_decode_cb(result, all_encoded, sizeof(*result), (size_t)ntasks);
assert(consumed==ntasks*encoded_nused);
/* Free temporary resources */
encoded = SS_FREE(encoded);
all_encoded = SS_FREE(all_encoded);
SAF_LEAVE(result);
}