1
1
The C++ bindings were not tracking keyvals properly -- they were
freeing some internal meta data when Free_keyval() was called, not
when the keyval was actually destroyed (keyvals are refcounted in the
C layer, just like all other MPI objects, because they can live for
long after their corresponding Free call is invoked).  This commit
fixes this problem and several other things:

 * Add infrastructure on the ompi_attribute_keyval_t for an "extra"
   destructor pointer that will be invoked during the "real"
   constructor (i.e., when OBJ_RELEASE puts the refcount to 0).  This
   allows calling back into the C++ layer to release meta data
   associated with the keyval.
 * Adjust all cases where keyvals are created to pass in relevant
   destructors (NULL or the C++ destructor).
 * Do essentially the same for MPI::Comm, MPI::Win, and MPI:Datatype:
   * Move several functions out of the .cc file into the _inln.h file
     since they no longer require locks
   * Make the 4 Create_keyval() functions call a common back-end
     keyval creation function that does the Right Thing depending on
     whether C or C++ function pointers were used for the keyval
     functions.  The back-end function does not call the corresponding
     C MPI_*_create_keyval function, but rather does the work itself
     so that it can associate a "destructor" callback for the C++
     bindings for when the keyval is actually destroyed.
   * Change a few type names to be more indicative of what they are
     (mostly dealing with keyvals [not "keys"]).
 * Add the 3 missing bindings for MPI::Comm::Create_keyval().
 * Remove MPI::Comm::comm_map (and associated types) because it's no
   longer necessary in the intercepts -- it was a by-product of being
   a portable C++ bindings layer.  Now we can just query the C layer
   directly to figure out what type a communicator is.  This solves
   some logistics / callback issues, too.
 * Rename several types, variables, and fix many comments in the
   back-end C attribute implementation to make the names really
   reflect what they are (keyvals vs. attributes).  The previous names
   heavily overloaded the name "key" and were ''extremely''
   confusing.

This commit was SVN r13565.

The following Trac tickets were found above:
  Ticket 817 --> https://svn.open-mpi.org/trac/ompi/ticket/817
Этот коммит содержится в:
Jeff Squyres 2007-02-08 23:50:04 +00:00
родитель 33619d6b43
Коммит 260f1fd468
22 изменённых файлов: 746 добавлений и 489 удалений

Просмотреть файл

@ -9,7 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -367,13 +367,13 @@ typedef struct attribute_value_t {
* Local functions
*/
static void attribute_value_construct(attribute_value_t *item);
static void ompi_attrkey_item_construct(ompi_attrkey_item_t *item);
static void ompi_attrkey_item_destruct(ompi_attrkey_item_t *item);
static void ompi_attribute_keyval_construct(ompi_attribute_keyval_t *keyval);
static void ompi_attribute_keyval_destruct(ompi_attribute_keyval_t *keyval);
static int set_value(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash, int key,
opal_hash_table_t **attr_hash, int key,
attribute_value_t *new_attr,
bool predefined, bool need_lock);
static int get_value(opal_hash_table_t *keyhash, int key,
static int get_value(opal_hash_table_t *attr_hash, int key,
attribute_value_t **attribute, int *flag);
static void *translate_to_c(attribute_value_t *val);
static MPI_Fint translate_to_fortran_mpi1(attribute_value_t *val);
@ -392,10 +392,10 @@ static OBJ_CLASS_INSTANCE(attribute_value_t,
/*
* ompi_attribute_entry_t classes
*/
static OBJ_CLASS_INSTANCE(ompi_attrkey_item_t,
static OBJ_CLASS_INSTANCE(ompi_attribute_keyval_t,
opal_object_t,
ompi_attrkey_item_construct,
ompi_attrkey_item_destruct);
ompi_attribute_keyval_construct,
ompi_attribute_keyval_destruct);
/*
@ -431,36 +431,42 @@ static void attribute_value_construct(attribute_value_t *item)
/*
* ompi_attrkey_item_t constructor / destructor
* ompi_attribute_keyval_t constructor / destructor
*/
static void
ompi_attrkey_item_construct(ompi_attrkey_item_t *item)
ompi_attribute_keyval_construct(ompi_attribute_keyval_t *keyval)
{
item->attr_type = UNUSED_ATTR;
item->attr_flag = 0;
item->copy_attr_fn.attr_communicator_copy_fn = NULL;
item->delete_attr_fn.attr_communicator_copy_fn = NULL;
item->extra_state = NULL;
keyval->attr_type = UNUSED_ATTR;
keyval->attr_flag = 0;
keyval->copy_attr_fn.attr_communicator_copy_fn = NULL;
keyval->delete_attr_fn.attr_communicator_copy_fn = NULL;
keyval->extra_state = NULL;
keyval->extra_destructor = NULL;
/* Set the item->key value to an invalid value so that we can know
/* Set the keyval->key value to an invalid value so that we can know
if it has been initialized with a proper value or not.
Specifically, the destructor may get invoked if we weren't able
to assign a key properly. So we don't want to try to remove it
from the table if it wasn't there. */
item->key = -1;
keyval->key = -1;
}
static void
ompi_attrkey_item_destruct(ompi_attrkey_item_t *item)
ompi_attribute_keyval_destruct(ompi_attribute_keyval_t *keyval)
{
/* THIS FUNCTION ASSUMES THAT THE CALLER ALREADY HAS OBTAINED THE
alock MUTEX! Remove the key entry from the hash and free the
key. */
alock MUTEX! Remove the keyval entry from the hash and free
the key. */
if (-1 != item->key) {
opal_hash_table_remove_value_uint32(keyval_hash, item->key);
FREE_KEY(item->key);
if (-1 != keyval->key) {
/* If the destructor function pointer is not NULL, call it */
if (NULL != keyval->extra_destructor) {
keyval->extra_destructor(keyval->key);
}
opal_hash_table_remove_value_uint32(keyval_hash, keyval->key);
FREE_KEY(keyval->key);
}
}
@ -481,7 +487,7 @@ int ompi_attr_init(void)
return MPI_ERR_SYSRESOURCE;
}
key_bitmap = OBJ_NEW(ompi_bitmap_t);
if (0 != ompi_bitmap_init(key_bitmap, 10)) {
if (0 != ompi_bitmap_init(key_bitmap, 32)) {
return MPI_ERR_SYSRESOURCE;
}
@ -527,9 +533,10 @@ int ompi_attr_finalize(void)
int ompi_attr_create_keyval(ompi_attribute_type_t type,
ompi_attribute_fn_ptr_union_t copy_attr_fn,
ompi_attribute_fn_ptr_union_t delete_attr_fn,
int *key, void *extra_state, int flags)
int *key, void *extra_state, int flags,
ompi_attribute_keyval_destructor_fn_t *destructor_fn)
{
ompi_attrkey_item_t *attrkey;
ompi_attribute_keyval_t *keyval;
int ret;
/* Protect against the user calling ompi_attr_destroy and then
@ -540,32 +547,33 @@ int ompi_attr_create_keyval(ompi_attribute_type_t type,
/* Allocate space for the list item */
attrkey = OBJ_NEW(ompi_attrkey_item_t);
if (NULL == attrkey) {
keyval = OBJ_NEW(ompi_attribute_keyval_t);
if (NULL == keyval) {
return MPI_ERR_SYSRESOURCE;
}
/* Fill in the list item (must be done before we set the attrkey
/* Fill in the list item (must be done before we set the keyval
on the keyval_hash in case some other thread immediately reads
it from the keyval_hash) */
attrkey->copy_attr_fn = copy_attr_fn;
attrkey->delete_attr_fn = delete_attr_fn;
attrkey->extra_state = extra_state;
attrkey->attr_type = type;
attrkey->attr_flag = flags;
attrkey->key = -1;
keyval->copy_attr_fn = copy_attr_fn;
keyval->delete_attr_fn = delete_attr_fn;
keyval->extra_state = extra_state;
keyval->attr_type = type;
keyval->attr_flag = flags;
keyval->key = -1;
keyval->extra_destructor = destructor_fn;
/* Create a new unique key and fill the hash */
OPAL_THREAD_LOCK(&alock);
ret = CREATE_KEY(key);
if (OMPI_SUCCESS == ret) {
attrkey->key = *key;
ret = opal_hash_table_set_value_uint32(keyval_hash, *key, attrkey);
keyval->key = *key;
ret = opal_hash_table_set_value_uint32(keyval_hash, *key, keyval);
}
if (OMPI_SUCCESS != ret) {
OBJ_RELEASE(attrkey);
OBJ_RELEASE(keyval);
OPAL_THREAD_UNLOCK(&alock);
return ret;
}
@ -579,7 +587,7 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
bool predefined)
{
int ret;
ompi_attrkey_item_t *key_item;
ompi_attribute_keyval_t *keyval;
/* Protect against the user calling ompi_attr_destroy and then
calling any of the functions which use it */
@ -591,11 +599,11 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
OPAL_THREAD_LOCK(&alock);
ret = opal_hash_table_get_value_uint32(keyval_hash, *key,
(void **) &key_item);
(void **) &keyval);
if ((OMPI_SUCCESS != ret) || (NULL == key_item) ||
(key_item->attr_type != type) ||
((!predefined) && (key_item->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
if ((OMPI_SUCCESS != ret) || (NULL == keyval) ||
(keyval->attr_type != type) ||
((!predefined) && (keyval->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
OPAL_THREAD_UNLOCK(&alock);
return OMPI_ERR_BAD_PARAM;
}
@ -608,7 +616,7 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
with it, else it will just decrement the reference count, so that when
the last attribute is deleted, this object gets deleted too */
OBJ_RELEASE(key_item);
OBJ_RELEASE(keyval);
OPAL_THREAD_UNLOCK(&alock);
return MPI_SUCCESS;
@ -616,10 +624,10 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
int ompi_attr_delete(ompi_attribute_type_t type, void *object,
opal_hash_table_t *keyhash, int key,
opal_hash_table_t *attr_hash, int key,
bool predefined, bool need_lock)
{
ompi_attrkey_item_t *key_item;
ompi_attribute_keyval_t *keyval;
int ret = OMPI_SUCCESS, err;
attribute_value_t *attr;
@ -642,39 +650,39 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
/* Check if the key is valid in the master keyval hash */
ret = opal_hash_table_get_value_uint32(keyval_hash, key,
(void **) &key_item);
(void **) &keyval);
if ((OMPI_SUCCESS != ret) || (NULL == key_item) ||
(key_item->attr_type!= type) ||
((!predefined) && (key_item->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
if ((OMPI_SUCCESS != ret) || (NULL == keyval) ||
(keyval->attr_type!= type) ||
((!predefined) && (keyval->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
ret = OMPI_ERR_BAD_PARAM;
goto exit;
}
/* Ensure that we don't have an empty keyhash */
/* Ensure that we don't have an empty attr_hash */
if (NULL == keyhash) {
if (NULL == attr_hash) {
ret = OMPI_ERR_BAD_PARAM;
goto exit;
}
/* Check if the key is valid for the communicator/window/dtype. If
yes, then delete the attribute and key entry from the object's key
yes, then delete the attribute and key entry from the object's
hash */
ret = opal_hash_table_get_value_uint32(keyhash, key, (void**) &attr);
ret = opal_hash_table_get_value_uint32(attr_hash, key, (void**) &attr);
if (OMPI_SUCCESS == ret) {
switch (type) {
case COMM_ATTR:
DELETE_ATTR_CALLBACKS(communicator, attr, key_item, object);
DELETE_ATTR_CALLBACKS(communicator, attr, keyval, object);
break;
case WIN_ATTR:
DELETE_ATTR_CALLBACKS(win, attr, key_item, object);
DELETE_ATTR_CALLBACKS(win, attr, keyval, object);
break;
case TYPE_ATTR:
DELETE_ATTR_CALLBACKS(datatype, attr, key_item, object);
DELETE_ATTR_CALLBACKS(datatype, attr, keyval, object);
break;
default:
@ -683,7 +691,7 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
}
OBJ_RELEASE(attr);
ret = opal_hash_table_remove_value_uint32(keyhash, key);
ret = opal_hash_table_remove_value_uint32(attr_hash, key);
if (OMPI_SUCCESS != ret) {
goto exit;
}
@ -698,7 +706,7 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
freed the last attribute that was using the keyval. */
if (OMPI_SUCCESS == ret) {
OBJ_RELEASE(key_item);
OBJ_RELEASE(keyval);
}
if (need_lock) {
@ -714,7 +722,7 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
* attribute.
*/
int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash,
opal_hash_table_t **attr_hash,
int key, void *attribute, bool predefined, bool need_lock)
{
attribute_value_t *new_attr = OBJ_NEW(attribute_value_t);
@ -724,7 +732,7 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
new_attr->av_value = attribute;
new_attr->av_set_from = OMPI_ATTRIBUTE_C;
return set_value(type, object, keyhash, key, new_attr,
return set_value(type, object, attr_hash, key, new_attr,
predefined, need_lock);
}
@ -734,7 +742,7 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
* an attribute.
*/
int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash,
opal_hash_table_t **attr_hash,
int key, MPI_Fint attribute,
bool predefined, bool need_lock)
{
@ -746,7 +754,7 @@ int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
new_attr->av_value = (void *) 0;
*new_attr->av_integer_pointer = attribute;
new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI1;
return set_value(type, object, keyhash, key, new_attr,
return set_value(type, object, attr_hash, key, new_attr,
predefined, need_lock);
}
@ -756,7 +764,7 @@ int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
* an attribute.
*/
int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash,
opal_hash_table_t **attr_hash,
int key, MPI_Aint attribute,
bool predefined, bool need_lock)
{
@ -767,7 +775,7 @@ int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
new_attr->av_value = (void *) attribute;
new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI2;
return set_value(type, object, keyhash, key, new_attr,
return set_value(type, object, attr_hash, key, new_attr,
predefined, need_lock);
}
@ -776,13 +784,13 @@ int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
* Front-end function called by the C MPI API functions to get
* attributes.
*/
int ompi_attr_get_c(opal_hash_table_t *keyhash, int key,
int ompi_attr_get_c(opal_hash_table_t *attr_hash, int key,
void **attribute, int *flag)
{
attribute_value_t *val = NULL;
int ret;
ret = get_value(keyhash, key, &val, flag);
ret = get_value(attr_hash, key, &val, flag);
if (MPI_SUCCESS == ret && 1 == *flag) {
*attribute = translate_to_c(val);
}
@ -795,13 +803,13 @@ int ompi_attr_get_c(opal_hash_table_t *keyhash, int key,
* Front-end function called by the Fortran MPI-1 API functions to get
* attributes.
*/
int ompi_attr_get_fortran_mpi1(opal_hash_table_t *keyhash, int key,
int ompi_attr_get_fortran_mpi1(opal_hash_table_t *attr_hash, int key,
MPI_Fint *attribute, int *flag)
{
attribute_value_t *val = NULL;
int ret;
ret = get_value(keyhash, key, &val, flag);
ret = get_value(attr_hash, key, &val, flag);
if (MPI_SUCCESS == ret && 1 == *flag) {
*attribute = translate_to_fortran_mpi1(val);
}
@ -814,13 +822,13 @@ int ompi_attr_get_fortran_mpi1(opal_hash_table_t *keyhash, int key,
* Front-end function called by the Fortran MPI-2 API functions to get
* attributes.
*/
int ompi_attr_get_fortran_mpi2(opal_hash_table_t *keyhash, int key,
int ompi_attr_get_fortran_mpi2(opal_hash_table_t *attr_hash, int key,
MPI_Aint *attribute, int *flag)
{
attribute_value_t *val = NULL;
int ret;
ret = get_value(keyhash, key, &val, flag);
ret = get_value(attr_hash, key, &val, flag);
if (MPI_SUCCESS == ret && 1 == *flag) {
*attribute = translate_to_fortran_mpi2(val);
}
@ -833,8 +841,8 @@ int ompi_attr_get_fortran_mpi2(opal_hash_table_t *keyhash, int key,
* Copy all the attributes from one MPI object to another
*/
int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
void *new_object, opal_hash_table_t *oldkeyhash,
opal_hash_table_t *newkeyhash)
void *new_object, opal_hash_table_t *oldattr_hash,
opal_hash_table_t *newattr_hash)
{
int ret;
int err;
@ -842,7 +850,7 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
int flag;
void *node, *in_node;
attribute_value_t *old_attr, *new_attr;
ompi_attrkey_item_t *hash_value;
ompi_attribute_keyval_t *hash_value;
/* Protect against the user calling ompi_attr_destroy and then
calling any of the functions which use it */
@ -852,7 +860,7 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
/* If there's nothing to do, just return */
if (NULL == oldkeyhash) {
if (NULL == oldattr_hash) {
return MPI_SUCCESS;
}
@ -862,17 +870,16 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
OPAL_THREAD_LOCK(&alock);
/* Get the first key-attr in the object's key hash */
ret = opal_hash_table_get_first_key_uint32(oldkeyhash, &key,
/* Get the first attribute in the object's hash */
ret = opal_hash_table_get_first_key_uint32(oldattr_hash, &key,
(void **) &old_attr,
&node);
/* While we still have some key-attr pair in the object's key
hash */
/* While we still have some attribute in the object's key hash */
while (OMPI_SUCCESS == ret) {
in_node = node;
/* Get the attr_item in the main keyval hash - so that we know
/* Get the keyval in the main keyval hash - so that we know
what the copy_attr_fn is */
err = opal_hash_table_get_value_uint32(keyval_hash, key,
@ -902,7 +909,7 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
break;
}
/* Hang this off the object's key hash */
/* Hang this off the object's hash */
/* The "predefined" parameter to ompi_attr_set() is set to 1,
so that no comparison is done for prdefined at all and it
@ -918,13 +925,13 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
} else {
new_attr->av_set_from = OMPI_ATTRIBUTE_C;
}
set_value(type, new_object, &newkeyhash, key,
set_value(type, new_object, &newattr_hash, key,
new_attr, true, false);
} else {
OBJ_RELEASE(new_attr);
}
ret = opal_hash_table_get_next_key_uint32(oldkeyhash, &key,
ret = opal_hash_table_get_next_key_uint32(oldattr_hash, &key,
(void **) &old_attr,
in_node, &node);
}
@ -940,7 +947,7 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
* Delete all the attributes on an MPI object
*/
int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
opal_hash_table_t *keyhash)
opal_hash_table_t *attr_hash)
{
int key_ret, del_ret;
uint32_t key, oldkey;
@ -954,7 +961,7 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
/* Ensure that the table is not empty */
if (NULL == keyhash) {
if (NULL == attr_hash) {
return MPI_SUCCESS;
}
@ -964,8 +971,8 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
OPAL_THREAD_LOCK(&alock);
/* Get the first key in local object's key hash */
key_ret = opal_hash_table_get_first_key_uint32(keyhash,
/* Get the first key in local object's hash */
key_ret = opal_hash_table_get_first_key_uint32(attr_hash,
&key, &old_attr,
&node);
del_ret = OMPI_SUCCESS;
@ -979,12 +986,12 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
/* Move to the next node */
key_ret = opal_hash_table_get_next_key_uint32(keyhash,
key_ret = opal_hash_table_get_next_key_uint32(attr_hash,
&key, &old_attr,
in_node, &node);
/* Now delete this attribute */
del_ret = ompi_attr_delete(type, object, keyhash, oldkey, true, false);
del_ret = ompi_attr_delete(type, object, attr_hash, oldkey, true, false);
}
/* All done */
@ -999,11 +1006,11 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
* Back-end function to set an attribute on an MPI object
*/
static int set_value(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash, int key,
opal_hash_table_t **attr_hash, int key,
attribute_value_t *new_attr,
bool predefined, bool need_lock)
{
ompi_attrkey_item_t *key_item;
ompi_attribute_keyval_t *keyval;
int ret, err;
attribute_value_t *old_attr;
bool had_old = false;
@ -1013,7 +1020,7 @@ static int set_value(ompi_attribute_type_t type, void *object,
if (NULL == keyval_hash) {
return MPI_ERR_INTERN;
}
if (NULL == keyhash) {
if (NULL == attr_hash) {
return MPI_ERR_INTERN;
}
@ -1027,41 +1034,41 @@ static int set_value(ompi_attribute_type_t type, void *object,
OPAL_THREAD_LOCK(&alock);
}
ret = opal_hash_table_get_value_uint32(keyval_hash, key,
(void **) &key_item);
(void **) &keyval);
/* If key not found */
if ((OMPI_SUCCESS != ret ) || (NULL == key_item) ||
(key_item->attr_type != type) ||
((!predefined) && (key_item->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
if ((OMPI_SUCCESS != ret ) || (NULL == keyval) ||
(keyval->attr_type != type) ||
((!predefined) && (keyval->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
if (need_lock) {
OPAL_THREAD_UNLOCK(&alock);
}
return OMPI_ERR_BAD_PARAM;
}
/* Do we need to make a new keyhash? */
/* Do we need to make a new attr_hash? */
if (NULL == *keyhash) {
ompi_attr_hash_init(keyhash);
if (NULL == *attr_hash) {
ompi_attr_hash_init(attr_hash);
}
/* Now see if the key is present in the object's key hash. If so,
delete the old attribute value. */
/* Now see if an attribute is already present in the object's hash
on the old keyval. If so, delete the old attribute value. */
ret = opal_hash_table_get_value_uint32(*keyhash, key, (void**) &old_attr);
ret = opal_hash_table_get_value_uint32(*attr_hash, key, (void**) &old_attr);
if (OMPI_SUCCESS == ret) {
switch (type) {
case COMM_ATTR:
DELETE_ATTR_CALLBACKS(communicator, old_attr, key_item, object);
DELETE_ATTR_CALLBACKS(communicator, old_attr, keyval, object);
break;
case WIN_ATTR:
DELETE_ATTR_CALLBACKS(win, old_attr, key_item, object);
DELETE_ATTR_CALLBACKS(win, old_attr, keyval, object);
break;
case TYPE_ATTR:
DELETE_ATTR_CALLBACKS(datatype, old_attr, key_item, object);
DELETE_ATTR_CALLBACKS(datatype, old_attr, keyval, object);
break;
default:
@ -1074,13 +1081,13 @@ static int set_value(ompi_attribute_type_t type, void *object,
OBJ_RELEASE(old_attr);
}
ret = opal_hash_table_set_value_uint32(*keyhash, key, new_attr);
ret = opal_hash_table_set_value_uint32(*attr_hash, key, new_attr);
/* Increase the reference count of the object, only if there was no
old atribute/no old entry in the object's key hash */
if (OMPI_SUCCESS == ret && !had_old) {
OBJ_RETAIN(key_item);
OBJ_RETAIN(keyval);
}
/* Release the lock if we grabbed it */
@ -1102,37 +1109,38 @@ static int set_value(ompi_attribute_type_t type, void *object,
* in small, standalone functions that are called from several
* different places.
*/
static int get_value(opal_hash_table_t *keyhash, int key,
static int get_value(opal_hash_table_t *attr_hash, int key,
attribute_value_t **attribute, int *flag)
{
int ret;
void *attr;
ompi_attrkey_item_t *key_item;
ompi_attribute_keyval_t *keyval;
/* According to MPI specs, the call is invalid if key is not
present in the main keyval hash at all. If no attribute is
associated with the key, then the call is valid and returns
FALSE in the flag argument */
/* According to MPI specs, the call is invalid if the keyval does
not exist (i.e., the key is not present in the main keyval
hash). If the keyval exists but no attribute is associated
with the key, then the call is valid and returns FALSE in the
flag argument */
*flag = 0;
OPAL_THREAD_LOCK(&alock);
ret = opal_hash_table_get_value_uint32(keyval_hash, key,
(void**) &key_item);
(void**) &keyval);
if (OMPI_ERR_NOT_FOUND == ret) {
OPAL_THREAD_UNLOCK(&alock);
return MPI_KEYVAL_INVALID;
}
/* If we have a null keyhash table, that means that nothing has
/* If we have a null attr_hash table, that means that nothing has
been cached on this object yet. So just return *flag = 0. */
if (NULL == keyhash) {
if (NULL == attr_hash) {
OPAL_THREAD_UNLOCK(&alock);
return OMPI_SUCCESS;
}
ret = opal_hash_table_get_value_uint32(keyhash, key, &attr);
ret = opal_hash_table_get_value_uint32(attr_hash, key, &attr);
OPAL_THREAD_UNLOCK(&alock);
if (OMPI_SUCCESS == ret) {
*attribute = (attribute_value_t*)attr;

Просмотреть файл

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -104,6 +105,8 @@ typedef int (MPI_Type_internal_copy_attr_function)(MPI_Datatype, int, void *,
typedef int (MPI_Win_internal_copy_attr_function)(MPI_Win, int, void *,
void *, void *, int *, MPI_Win);
typedef void (ompi_attribute_keyval_destructor_fn_t)(int);
/* Union to take care of proper casting of the function pointers
passed from the front end functions depending on the type. This
will avoid casting function pointers to void* */
@ -145,7 +148,7 @@ union ompi_attribute_fortran_ptr_t {
*/
typedef union ompi_attribute_fortran_ptr_t ompi_attribute_fortran_ptr_t;
struct ompi_attrkey_item_t {
struct ompi_attribute_keyval_t {
opal_object_t super;
ompi_attribute_type_t attr_type; /**< One of COMM/WIN/DTYPE. This
will be used to cast the
@ -160,9 +163,13 @@ struct ompi_attrkey_item_t {
void *extra_state; /**< Extra state of the attribute */
int key; /**< Keep a track of which key this item belongs to, so that
the key can be deleted when this object is destroyed */
/** If non-null, call this function when the OBJ destructor for this
object is invoked */
ompi_attribute_keyval_destructor_fn_t *extra_destructor;
};
typedef struct ompi_attrkey_item_t ompi_attrkey_item_t;
typedef struct ompi_attribute_keyval_t ompi_attribute_keyval_t;
/* Functions */
@ -174,14 +181,14 @@ typedef struct ompi_attrkey_item_t ompi_attrkey_item_t;
*/
static inline
int ompi_attr_hash_init(opal_hash_table_t **keyhash)
int ompi_attr_hash_init(opal_hash_table_t **hash)
{
*keyhash = OBJ_NEW(opal_hash_table_t);
if (NULL == keyhash) {
*hash = OBJ_NEW(opal_hash_table_t);
if (NULL == hash) {
fprintf(stderr, "Error while creating the local attribute list\n");
return MPI_ERR_SYSRESOURCE;
}
if (OMPI_SUCCESS != opal_hash_table_init(*keyhash, ATTR_HASH_SIZE)) {
if (OMPI_SUCCESS != opal_hash_table_init(*hash, ATTR_HASH_SIZE)) {
return MPI_ERR_SYSRESOURCE;
}
@ -189,7 +196,7 @@ int ompi_attr_hash_init(opal_hash_table_t **keyhash)
}
/**
* Initialize the main attribute hash that stores the key and meta data
* Initialize the main attribute hash that stores the keyvals and meta data
*
* @return OMPI return code
*/
@ -197,7 +204,7 @@ int ompi_attr_hash_init(opal_hash_table_t **keyhash)
int ompi_attr_init(void);
/**
* Destroy the main attribute hash that stores the key and meta data
* Destroy the main attribute hash that stores the keyvals and meta data
*/
int ompi_attr_finalize(void);
@ -234,9 +241,10 @@ int ompi_attr_finalize(void);
*/
int ompi_attr_create_keyval(ompi_attribute_type_t type,
ompi_attribute_fn_ptr_union_t copy_attr_fn,
ompi_attribute_fn_ptr_union_t delete_attr_fn,
int *key, void *extra_state, int flags);
ompi_attribute_fn_ptr_union_t copy_attr_fn,
ompi_attribute_fn_ptr_union_t delete_attr_fn,
int *key, void *extra_state, int flags,
ompi_attribute_keyval_destructor_fn_t *destructor);
/**
* Free an attribute keyval
@ -253,14 +261,14 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
*
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (IN)
* @param keyhash The attribute hash table hanging on the object(IN/OUT)
* @param attr_hash The attribute hash table hanging on the object(IN/OUT)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (IN)
* @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code
*
* If (*keyhash) == NULL, a new keyhash will be created and
* If (*attr_hash) == NULL, a new hash will be created and
* initialized.
*
* Note that need_lock should *always* be true when this function is
@ -281,7 +289,7 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
* (read: better) this way.
*/
int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash,
opal_hash_table_t **attr_hash,
int key, void *attribute, bool predefined, bool need_lock);
/**
@ -290,14 +298,14 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
*
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (IN)
* @param keyhash The attribute hash table hanging on the object(IN/OUT)
* @param attr_hash The attribute hash table hanging on the object(IN/OUT)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (IN)
* @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code
*
* If (*keyhash) == NULL, a new keyhash will be created and
* If (*attr_hash) == NULL, a new hash will be created and
* initialized.
*
* Note that need_lock should *always* be true when this function is
@ -318,7 +326,7 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
* (read: better) this way.
*/
int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash,
opal_hash_table_t **attr_hash,
int key, MPI_Fint attribute,
bool predefined, bool need_lock);
@ -328,14 +336,14 @@ int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
*
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (IN)
* @param keyhash The attribute hash table hanging on the object(IN/OUT)
* @param attr_hash The attribute hash table hanging on the object(IN/OUT)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (IN)
* @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code
*
* If (*keyhash) == NULL, a new keyhash will be created and
* If (*attr_hash) == NULL, a new hash will be created and
* initialized.
*
* Note that need_lock should *always* be true when this function is
@ -356,14 +364,14 @@ int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
* (read: better) this way.
*/
int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
opal_hash_table_t **keyhash,
opal_hash_table_t **attr_hash,
int key, MPI_Aint attribute,
bool predefined, bool need_lock);
/**
* Get an attribute on the comm/win/datatype in a form valid for C.
*
* @param keyhash The attribute hash table hanging on the object(IN)
* @param attr_hash The attribute hash table hanging on the object(IN)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated
@ -382,7 +390,7 @@ int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
* (read: better) this way.
*/
int ompi_attr_get_c(opal_hash_table_t *keyhash, int key,
int ompi_attr_get_c(opal_hash_table_t *attr_hash, int key,
void **attribute, int *flag);
@ -390,7 +398,7 @@ int ompi_attr_get_c(opal_hash_table_t *keyhash, int key,
* Get an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-1.
*
* @param keyhash The attribute hash table hanging on the object(IN)
* @param attr_hash The attribute hash table hanging on the object(IN)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated
@ -409,7 +417,7 @@ int ompi_attr_get_c(opal_hash_table_t *keyhash, int key,
* (read: better) this way.
*/
int ompi_attr_get_fortran_mpi1(opal_hash_table_t *keyhash, int key,
int ompi_attr_get_fortran_mpi1(opal_hash_table_t *attr_hash, int key,
MPI_Fint *attribute, int *flag);
@ -417,7 +425,7 @@ int ompi_attr_get_fortran_mpi1(opal_hash_table_t *keyhash, int key,
* Get an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-2.
*
* @param keyhash The attribute hash table hanging on the object(IN)
* @param attrhash The attribute hash table hanging on the object(IN)
* @param key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated
@ -436,7 +444,7 @@ int ompi_attr_get_fortran_mpi1(opal_hash_table_t *keyhash, int key,
* (read: better) this way.
*/
int ompi_attr_get_fortran_mpi2(opal_hash_table_t *keyhash, int key,
int ompi_attr_get_fortran_mpi2(opal_hash_table_t *attr_hash, int key,
MPI_Aint *attribute, int *flag);
@ -444,7 +452,7 @@ int ompi_attr_get_fortran_mpi2(opal_hash_table_t *keyhash, int key,
* Delete an attribute on the comm/win/datatype
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (IN)
* @param keyhash The attribute hash table hanging on the object(IN)
* @param attr_hash The attribute hash table hanging on the object(IN)
* @param key Key val for the attribute (IN)
* @param predefined Whether the key is predefined or not 0/1 (IN)
* @param need_lock Whether we need to need to lock the keyval_lock or not
@ -458,7 +466,7 @@ int ompi_attr_get_fortran_mpi2(opal_hash_table_t *keyhash, int key,
*/
int ompi_attr_delete(ompi_attribute_type_t type, void *object,
opal_hash_table_t *keyhash , int key,
opal_hash_table_t *attr_hash , int key,
bool predefined, bool need_lock);
@ -469,14 +477,14 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param old_object The old COMM/WIN/DTYPE object (IN)
* @param new_object The new COMM/WIN/DTYPE object (IN)
* @param keyhash The attribute hash table hanging on old object(IN)
* @param newkeyhash The attribute hash table hanging on new object(IN)
* @param attr_hash The attribute hash table hanging on old object(IN)
* @param newattr_hash The attribute hash table hanging on new object(IN)
* @return OMPI error code
*
*/
int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
void *new_object, opal_hash_table_t *oldkeyhash,
void *new_object, opal_hash_table_t *oldattr_hash,
opal_hash_table_t *newkeyhash);
@ -485,13 +493,13 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
* object in one shot
* @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The COMM/WIN/DTYPE object (IN)
* @param keyhash The attribute hash table hanging on the object(IN)
* @param attr_hash The attribute hash table hanging on the object(IN)
* @return OMPI error code
*
*/
int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
opal_hash_table_t *keyhash);
opal_hash_table_t *attr_hash);
/**

Просмотреть файл

@ -10,6 +10,7 @@
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2006 University of Houston. All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -346,7 +347,7 @@ static int create_comm(int target_keyval, bool want_inherit)
(want_inherit ? MPI_COMM_DUP_FN : MPI_COMM_NULL_COPY_FN);
del.attr_communicator_delete_fn = MPI_COMM_NULL_DELETE_FN;
err = ompi_attr_create_keyval(COMM_ATTR, copy, del,
&keyval, NULL, OMPI_KEYVAL_PREDEFINED);
&keyval, NULL, OMPI_KEYVAL_PREDEFINED, NULL);
if (MPI_SUCCESS != err) {
return err;
}
@ -375,7 +376,7 @@ static int create_win(int target_keyval)
copy.attr_win_copy_fn = (MPI_Win_internal_copy_attr_function*)MPI_WIN_NULL_COPY_FN;
del.attr_win_delete_fn = MPI_WIN_NULL_DELETE_FN;
err = ompi_attr_create_keyval(WIN_ATTR, copy, del,
&keyval, NULL, OMPI_KEYVAL_PREDEFINED);
&keyval, NULL, OMPI_KEYVAL_PREDEFINED, NULL);
if (MPI_SUCCESS != err) {
return err;
}

Просмотреть файл

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -53,7 +54,7 @@ int MPI_Comm_create_keyval(MPI_Comm_copy_attr_function *comm_copy_attr_fn,
del_fn.attr_communicator_delete_fn = comm_delete_attr_fn;
ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn,
del_fn, comm_keyval, extra_state, 0);
del_fn, comm_keyval, extra_state, 0, NULL);
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME);
}

Просмотреть файл

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -55,6 +56,6 @@ int MPI_Keyval_create(MPI_Copy_function *copy_attr_fn,
del_fn.attr_communicator_delete_fn = delete_attr_fn;
ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn,
del_fn, keyval, extra_state, 0);
del_fn, keyval, extra_state, 0, NULL);
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME);
}

Просмотреть файл

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -55,7 +56,7 @@ int MPI_Type_create_keyval(MPI_Type_copy_attr_function *type_copy_attr_fn,
del_fn.attr_datatype_delete_fn = type_delete_attr_fn;
ret = ompi_attr_create_keyval(TYPE_ATTR, copy_fn, del_fn,
type_keyval, extra_state, 0);
type_keyval, extra_state, 0, NULL);
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, ret, FUNC_NAME);
}

Просмотреть файл

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -52,6 +53,6 @@ int MPI_Win_create_keyval(MPI_Win_copy_attr_function *win_copy_attr_fn,
del_fn.attr_win_delete_fn = win_delete_attr_fn;
ret = ompi_attr_create_keyval(WIN_ATTR, copy_fn, del_fn,
win_keyval, extra_state, 0);
win_keyval, extra_state, 0, NULL);
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME);
}

Просмотреть файл

@ -10,6 +10,7 @@
// University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -22,6 +23,12 @@
#include "ompi/mpi/cxx/mpicxx.h"
#include "opal/threads/mutex.h"
#include "ompi/communicator/communicator.h"
#include "ompi/attribute/attribute.h"
#include "ompi/errhandler/errhandler.h"
static void cxx_comm_keyval_destructor(int keyval);
//
// These functions are all not inlined because they need to use locks to
// protect the handle maps and it would be bad to have those in headers
@ -43,20 +50,6 @@ MPI::Comm::Comm(const Comm_Null& data) : Comm_Null(data)
}
void
MPI::Comm::Free(void)
{
MPI_Comm save = mpi_comm;
(void)MPI_Comm_free(&mpi_comm);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Comm::mpi_comm_map[save] != 0)
delete MPI::Comm::mpi_comm_map[save];
MPI::Comm::mpi_comm_map.erase(save);
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
}
void
MPI::Comm::Set_errhandler(const MPI::Errhandler& errhandler)
{
@ -71,60 +64,83 @@ MPI::Comm::Set_errhandler(const MPI::Errhandler& errhandler)
//JGS I took the const out because it causes problems when trying to
//call this function with the predefined NULL_COPY_FN etc.
int
MPI::Comm::Create_keyval(MPI::Comm::_MPI2CPP_COPYATTRFN_* comm_copy_attr_fn,
MPI::Comm::_MPI2CPP_DELETEATTRFN_* comm_delete_attr_fn,
void* extra_state)
MPI::Comm::do_create_keyval(MPI_Comm_copy_attr_function* c_copy_fn,
MPI_Comm_delete_attr_function* c_delete_fn,
Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state)
{
int keyval;
(void)MPI_Keyval_create(ompi_mpi_cxx_comm_copy_attr_intercept,
ompi_mpi_cxx_comm_delete_attr_intercept,
&keyval, extra_state);
key_pair_t* copy_and_delete =
new key_pair_t(comm_copy_attr_fn, comm_delete_attr_fn);
int keyval, ret, count = 0;
ompi_attribute_fn_ptr_union_t copy_fn;
ompi_attribute_fn_ptr_union_t delete_fn;
Copy_attr_function *cxx_pair_copy = NULL;
Delete_attr_function *cxx_pair_delete = NULL;
// We do not call MPI_Comm_create_keyval() here because we need to
// pass in a special destructor to the backend keyval creation
// that gets invoked when the keyval's reference count goes to 0
// and is finally destroyed (i.e., clean up some caching/lookup
// data here in the C++ bindings layer). This destructor is
// *only* used in the C++ bindings, so it's not set by the C
// MPI_Comm_create_keyval(). Hence, we do all the work here (and
// ensure to set the destructor atomicly when the keyval is
// created).
// Error check. Must have exactly 2 non-NULL function pointers.
if (NULL != c_copy_fn) {
copy_fn.attr_communicator_copy_fn =
(MPI_Comm_internal_copy_attr_function*) c_copy_fn;
++count;
}
if (NULL != c_delete_fn) {
delete_fn.attr_communicator_delete_fn = c_delete_fn;
++count;
}
if (NULL != cxx_copy_fn) {
copy_fn.attr_communicator_copy_fn =
(MPI_Comm_internal_copy_attr_function*) ompi_mpi_cxx_comm_copy_attr_intercept;
cxx_pair_copy = cxx_copy_fn;
++count;
}
if (NULL != cxx_delete_fn) {
delete_fn.attr_communicator_delete_fn =
ompi_mpi_cxx_comm_delete_attr_intercept;
cxx_pair_delete = cxx_delete_fn;
++count;
}
if (2 != count) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
"MPI::Comm::Create_keyval");
}
ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn, delete_fn,
&keyval, extra_state, 0,
cxx_comm_keyval_destructor);
if (OMPI_SUCCESS != ret) {
return ret;
}
keyval_pair_t* copy_and_delete =
new keyval_pair_t(cxx_pair_copy, cxx_pair_delete);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Comm::mpi_comm_key_fn_map[keyval] = copy_and_delete;
MPI::Comm::mpi_comm_keyval_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
void
MPI::Comm::Free_keyval(int& comm_keyval)
// This function is called back out of the keyval destructor in the C
// layer when the keyval is not be used by any attributes anymore,
// anywhere. So we can definitely safely remove the entry for this
// keyval from the C++ map.
static void cxx_comm_keyval_destructor(int keyval)
{
int save = comm_keyval;
(void)MPI_Keyval_free(&comm_keyval);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Comm::mpi_comm_key_fn_map[save] != 0)
delete MPI::Comm::mpi_comm_key_fn_map[save];
MPI::Comm::mpi_comm_key_fn_map.erase(save);
if (MPI::Comm::mpi_comm_keyval_fn_map.end() !=
MPI::Comm::mpi_comm_keyval_fn_map.find(keyval) &&
NULL != MPI::Comm::mpi_comm_keyval_fn_map[keyval]) {
delete MPI::Comm::mpi_comm_keyval_fn_map[keyval];
MPI::Comm::mpi_comm_keyval_fn_map.erase(keyval);
}
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
}
void
MPI::Comm::Set_attr(int comm_keyval, const void* attribute_val) const
{
CommType type;
int status;
(void)MPI_Comm_test_inter(mpi_comm, &status);
if (status) {
type = eIntercomm;
}
else {
(void)MPI_Topo_test(mpi_comm, &status);
if (status == MPI_CART)
type = eCartcomm;
else if (status == MPI_GRAPH)
type = eGraphcomm;
else
type = eIntracomm;
}
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Comm::mpi_comm_map[mpi_comm] == 0) {
comm_pair_t* comm_type = new comm_pair_t((Comm*) this, type);
MPI::Comm::mpi_comm_map[mpi_comm] = comm_type;
}
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
(void)MPI_Attr_put(mpi_comm, comm_keyval, (void*) attribute_val);
}

Просмотреть файл

@ -10,7 +10,7 @@
// University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
// Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -391,12 +391,31 @@ public:
// Keys and Attributes
//
//JGS I took the const out because it causes problems when trying to
//call this function with the predefined NULL_COPY_FN etc.
// Need 4 overloaded versions of this function because per the
// MPI-2 spec, you can mix-n-match the C predefined functions with
// C++ functions.
static int Create_keyval(Copy_attr_function* comm_copy_attr_fn,
Delete_attr_function* comm_delete_attr_fn,
void* extra_state);
Delete_attr_function* comm_delete_attr_fn,
void* extra_state);
static int Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
MPI_Comm_delete_attr_function* comm_delete_attr_fn,
void* extra_state);
static int Create_keyval(Copy_attr_function* comm_copy_attr_fn,
MPI_Comm_delete_attr_function* comm_delete_attr_fn,
void* extra_state);
static int Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
Delete_attr_function* comm_delete_attr_fn,
void* extra_state);
protected:
static int do_create_keyval(MPI_Comm_copy_attr_function* c_copy_fn,
MPI_Comm_delete_attr_function* c_delete_fn,
Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state);
public:
static void Free_keyval(int& comm_keyval);
virtual void Set_attr(int comm_keyval, const void* attribute_val) const;
@ -428,16 +447,12 @@ public: // JGS hmmm, these used by errhandler_intercept
Errhandler* my_errhandler;
typedef ::std::pair<Comm*, CommType> comm_pair_t;
typedef ::std::map<MPI_Comm, comm_pair_t*> mpi_comm_map_t;
static mpi_comm_map_t mpi_comm_map;
typedef ::std::map<MPI_Comm, Comm*> mpi_comm_err_map_t;
static mpi_comm_err_map_t mpi_comm_err_map;
typedef ::std::pair<Comm::_MPI2CPP_COPYATTRFN_*, Comm::_MPI2CPP_DELETEATTRFN_*> key_pair_t;
typedef ::std::map<int, key_pair_t*> mpi_comm_key_fn_map_t;
static mpi_comm_key_fn_map_t mpi_comm_key_fn_map;
typedef ::std::pair<Comm::_MPI2CPP_COPYATTRFN_*, Comm::_MPI2CPP_DELETEATTRFN_*> keyval_pair_t;
typedef ::std::map<int, keyval_pair_t*> mpi_comm_keyval_fn_map_t;
static mpi_comm_keyval_fn_map_t mpi_comm_keyval_fn_map;
void init() {
my_errhandler = (Errhandler*)0;

Просмотреть файл

@ -10,6 +10,7 @@
// University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -283,7 +284,12 @@ MPI::Comm::Compare(const MPI::Comm & comm1,
return result;
}
inline void
MPI::Comm::Free(void)
{
(void)MPI_Comm_free(&mpi_comm);
}
inline bool
MPI::Comm::Is_inter() const
{
@ -546,6 +552,70 @@ MPI::Comm::Create_errhandler(MPI::Comm::_MPI2CPP_ERRHANDLERFN_* function)
return temp;
}
// 1) original Create_keyval that takes the first 2 arguments as C++
// functions
inline int
MPI::Comm::Create_keyval(MPI::Comm::Copy_attr_function* comm_copy_attr_fn,
MPI::Comm::Delete_attr_function* comm_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(NULL, NULL,
comm_copy_attr_fn, comm_delete_attr_fn,
extra_state);
}
// 2) overload Create_keyval to take the first 2 arguments as C
// functions
inline int
MPI::Comm::Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
MPI_Comm_delete_attr_function* comm_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(comm_copy_attr_fn, comm_delete_attr_fn,
NULL, NULL,
extra_state);
}
// 3) overload Create_keyval to take the first 2 arguments as C++ & C
// functions
inline int
MPI::Comm::Create_keyval(MPI::Comm::Copy_attr_function* comm_copy_attr_fn,
MPI_Comm_delete_attr_function* comm_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(NULL, comm_delete_attr_fn,
comm_copy_attr_fn, NULL,
extra_state);
}
// 4) overload Create_keyval to take the first 2 arguments as C & C++
// functions
inline int
MPI::Comm::Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
MPI::Comm::Delete_attr_function* comm_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(comm_copy_attr_fn, NULL,
NULL, comm_delete_attr_fn,
extra_state);
}
inline void
MPI::Comm::Free_keyval(int& comm_keyval)
{
(void) MPI_Keyval_free(&comm_keyval);
}
inline void
MPI::Comm::Set_attr(int comm_keyval, const void* attribute_val) const
{
(void)MPI_Attr_put(mpi_comm, comm_keyval, (void*) attribute_val);
}
inline bool
MPI::Comm::Get_attr(int comm_keyval, void* attribute_val) const
{

Просмотреть файл

@ -3,6 +3,7 @@
// Copyright (c) 2006 Los Alamos National Security, LLC. All rights
// reserved.
// Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -15,6 +16,11 @@
#include "ompi/mpi/cxx/mpicxx.h"
#include "opal/threads/mutex.h"
#include "ompi/communicator/communicator.h"
#include "ompi/attribute/attribute.h"
#include "ompi/errhandler/errhandler.h"
static void cxx_type_keyval_destructor(int keyval);
void
MPI::Datatype::Free()
@ -28,95 +34,85 @@ MPI::Datatype::Free()
}
// 1) original Create_keyval that takes the first 2 arguments as C++ macros
int
MPI::Datatype::Create_keyval(MPI::Datatype::Copy_attr_function* type_copy_attr_fn,
MPI::Datatype::Delete_attr_function* type_delete_attr_fn,
void* extra_state)
MPI::Datatype::do_create_keyval(MPI_Type_copy_attr_function* c_copy_fn,
MPI_Type_delete_attr_function* c_delete_fn,
Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state)
{
int keyval;
(void) MPI_Type_create_keyval(ompi_mpi_cxx_type_copy_attr_intercept,
ompi_mpi_cxx_type_delete_attr_intercept,
&keyval, extra_state);
key_pair_t* copy_and_delete =
new key_pair_t(type_copy_attr_fn, type_delete_attr_fn);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Datatype::mpi_type_key_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
int keyval, ret, count = 0;
ompi_attribute_fn_ptr_union_t copy_fn;
ompi_attribute_fn_ptr_union_t delete_fn;
Copy_attr_function *cxx_pair_copy = NULL;
Delete_attr_function *cxx_pair_delete = NULL;
// 2) overload Create_keyval to take the first 2 arguments as C macros
int
MPI::Datatype::Create_keyval(MPI_Type_copy_attr_function* type_copy_attr_fn,
MPI_Type_delete_attr_function* type_delete_attr_fn,
void* extra_state)
{
int keyval;
(void) MPI_Type_create_keyval(type_copy_attr_fn,
type_delete_attr_fn,
&keyval, extra_state);
return keyval;
}
// We do not call MPI_Type_create_keyval() here because we need to
// pass in a special destructor to the backend keyval creation
// that gets invoked when the keyval's reference count goes to 0
// and is finally destroyed (i.e., clean up some caching/lookup
// data here in the C++ bindings layer). This destructor is
// *only* used in the C++ bindings, so it's not set by the C
// MPI_Type_create_keyval(). Hence, we do all the work here (and
// ensure to set the destructor atomicly when the keyval is
// created).
// 3) overload Create_keyval to take the first 2 arguments as C++ & C macros
int
MPI::Datatype::Create_keyval(MPI::Datatype::Copy_attr_function* type_copy_attr_fn,
MPI_Type_delete_attr_function* type_delete_attr_fn,
void* extra_state)
{
int keyval;
// use a dummy attr_fn to create the c++ key pair
MPI::Datatype::Delete_attr_function* dummy_type_delete_attr_fn = NULL;
(void) MPI_Type_create_keyval(ompi_mpi_cxx_type_copy_attr_intercept,
type_delete_attr_fn,
&keyval, extra_state);
key_pair_t* copy_and_delete =
new key_pair_t(type_copy_attr_fn, dummy_type_delete_attr_fn);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Datatype::mpi_type_key_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
// Error check. Must have exactly 2 non-NULL function pointers.
if (NULL != c_copy_fn) {
copy_fn.attr_datatype_copy_fn =
(MPI_Type_internal_copy_attr_function*) c_copy_fn;
++count;
}
if (NULL != c_delete_fn) {
delete_fn.attr_datatype_delete_fn = c_delete_fn;
++count;
}
if (NULL != cxx_copy_fn) {
copy_fn.attr_datatype_copy_fn =
(MPI_Type_internal_copy_attr_function*) ompi_mpi_cxx_type_copy_attr_intercept;
cxx_pair_copy = cxx_copy_fn;
++count;
}
if (NULL != cxx_delete_fn) {
delete_fn.attr_datatype_delete_fn =
ompi_mpi_cxx_type_delete_attr_intercept;
cxx_pair_delete = cxx_delete_fn;
++count;
}
if (2 != count) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
"MPI::Datatype::Create_keyval");
}
// 4) overload Create_keyval to take the first 2 arguments as C & C++ macros
int
MPI::Datatype::Create_keyval(MPI_Type_copy_attr_function* type_copy_attr_fn,
MPI::Datatype::Delete_attr_function* type_delete_attr_fn,
void* extra_state)
{
int keyval;
// use a dummy attr_fn to create the c++ key pair
MPI::Datatype::Copy_attr_function* dummy_type_copy_attr_fn = NULL;
(void) MPI_Type_create_keyval(type_copy_attr_fn,
ompi_mpi_cxx_type_delete_attr_intercept,
&keyval, extra_state);
key_pair_t* copy_and_delete =
new key_pair_t(dummy_type_copy_attr_fn, type_delete_attr_fn);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Datatype::mpi_type_key_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
ret = ompi_attr_create_keyval(TYPE_ATTR, copy_fn, delete_fn,
&keyval, extra_state, 0,
cxx_type_keyval_destructor);
if (OMPI_SUCCESS != ret) {
return ret;
}
void
MPI::Datatype::Free_keyval(int& type_keyval)
{
int save = type_keyval;
(void) MPI_Type_free_keyval(&type_keyval);
keyval_pair_t* copy_and_delete =
new keyval_pair_t(cxx_pair_copy, cxx_pair_delete);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Datatype::mpi_type_key_fn_map.erase(save);
MPI::Datatype::mpi_type_keyval_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
// This function is called back out of the keyval destructor in the C
// layer when the keyval is not be used by any attributes anymore,
// anywhere. So we can definitely safely remove the entry for this
// keyval from the C++ map.
static void cxx_type_keyval_destructor(int keyval)
{
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Datatype::mpi_type_keyval_fn_map.end() !=
MPI::Datatype::mpi_type_keyval_fn_map.find(keyval) &&
NULL != MPI::Datatype::mpi_type_keyval_fn_map[keyval]) {
delete MPI::Datatype::mpi_type_keyval_fn_map[keyval];
MPI::Datatype::mpi_type_keyval_fn_map.erase(keyval);
}
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
}
void
MPI::Datatype::Set_attr(int type_keyval, const void* attribute_val)
{
(void) MPI_Type_set_attr(mpi_datatype, type_keyval, const_cast<void *>(attribute_val));
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Datatype::mpi_type_map[mpi_datatype] == 0) {
MPI::Datatype::mpi_type_map[mpi_datatype] = (Datatype*) this;
}
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
}

Просмотреть файл

@ -11,7 +11,7 @@
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2006-2007 Sun Microsystems, Inc. All rights reserved.
// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
// Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -161,7 +161,10 @@ public:
//
virtual Datatype Dup() const;
// Need 4 overloaded versions of this function because per the
// MPI-2 spec, you can mix-n-match the C predefined functions with
// C++ functions.
static int Create_keyval(Copy_attr_function* type_copy_attr_fn,
Delete_attr_function* type_delete_attr_fn,
void* extra_state);
@ -175,6 +178,17 @@ public:
Delete_attr_function* type_delete_attr_fn,
void* extra_state);
protected:
// Back-end function to do the heavy lifting for creating the
// keyval
static int do_create_keyval(MPI_Type_copy_attr_function* c_copy_fn,
MPI_Type_delete_attr_function* c_delete_fn,
Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state);
public:
virtual void Delete_attr(int type_keyval);
static void Free_keyval(int& type_keyval);
@ -209,9 +223,9 @@ public:
typedef ::std::map<MPI_Datatype, Datatype*> mpi_type_map_t;
static mpi_type_map_t mpi_type_map;
typedef ::std::pair<Datatype::Copy_attr_function*, Datatype::Delete_attr_function*> key_pair_t;
typedef ::std::map<int, key_pair_t*> mpi_type_key_fn_map_t;
static mpi_type_key_fn_map_t mpi_type_key_fn_map;
typedef ::std::pair<Datatype::Copy_attr_function*, Datatype::Delete_attr_function*> keyval_pair_t;
typedef ::std::map<int, keyval_pair_t*> mpi_type_keyval_fn_map_t;
static mpi_type_keyval_fn_map_t mpi_type_keyval_fn_map;
};

Просмотреть файл

@ -197,13 +197,69 @@ MPI::Datatype::Dup() const
}
// 1) original Create_keyval that takes the first 2 arguments as C++
// functions
inline int
MPI::Datatype::Create_keyval(MPI::Datatype::Copy_attr_function* type_copy_attr_fn,
MPI::Datatype::Delete_attr_function* type_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(NULL, NULL,
type_copy_attr_fn, type_delete_attr_fn,
extra_state);
}
// 2) overload Create_keyval to take the first 2 arguments as C
// functions
inline int
MPI::Datatype::Create_keyval(MPI_Type_copy_attr_function* type_copy_attr_fn,
MPI_Type_delete_attr_function* type_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(type_copy_attr_fn, type_delete_attr_fn,
NULL, NULL,
extra_state);
}
// 3) overload Create_keyval to take the first 2 arguments as C++ & C
// functions
inline int
MPI::Datatype::Create_keyval(MPI::Datatype::Copy_attr_function* type_copy_attr_fn,
MPI_Type_delete_attr_function* type_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(NULL, type_delete_attr_fn,
type_copy_attr_fn, NULL,
extra_state);
}
// 4) overload Create_keyval to take the first 2 arguments as C & C++
// functions
inline int
MPI::Datatype::Create_keyval(MPI_Type_copy_attr_function* type_copy_attr_fn,
MPI::Datatype::Delete_attr_function* type_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(type_copy_attr_fn, NULL,
NULL, type_delete_attr_fn,
extra_state);
}
inline void
MPI::Datatype::Delete_attr(int type_keyval)
{
(void) MPI_Type_delete_attr(mpi_datatype, type_keyval);
}
inline void
MPI::Datatype::Free_keyval(int& type_keyval)
{
(void) MPI_Type_free_keyval(&type_keyval);
}
inline bool
MPI::Datatype::Get_attr(int type_keyval,
@ -251,7 +307,11 @@ MPI::Datatype::Get_name(char* type_name, int& resultlen) const
(void) MPI_Type_get_name(mpi_datatype, type_name, &resultlen);
}
inline void
MPI::Datatype::Set_attr(int type_keyval, const void* attribute_val)
{
(void) MPI_Type_set_attr(mpi_datatype, type_keyval, const_cast<void *>(attribute_val));
}
inline void
MPI::Datatype::Set_name(const char* type_name)

Просмотреть файл

@ -10,7 +10,7 @@
// University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
// Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -24,17 +24,17 @@
#include "ompi_config.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/communicator/communicator.h"
#include "opal/threads/mutex.h"
MPI::Comm::mpi_comm_map_t MPI::Comm::mpi_comm_map;
MPI::Comm::mpi_comm_err_map_t MPI::Comm::mpi_comm_err_map;
MPI::Comm::mpi_comm_key_fn_map_t MPI::Comm::mpi_comm_key_fn_map;
MPI::Comm::mpi_comm_keyval_fn_map_t MPI::Comm::mpi_comm_keyval_fn_map;
MPI::Win::mpi_win_map_t MPI::Win::mpi_win_map;
MPI::Win::mpi_win_key_fn_map_t MPI::Win::mpi_win_key_fn_map;
MPI::Win::mpi_win_keyval_fn_map_t MPI::Win::mpi_win_keyval_fn_map;
MPI::Datatype::mpi_type_map_t MPI::Datatype::mpi_type_map;
MPI::Datatype::mpi_type_key_fn_map_t MPI::Datatype::mpi_type_key_fn_map;
MPI::Datatype::mpi_type_keyval_fn_map_t MPI::Datatype::mpi_type_keyval_fn_map;
MPI::File::mpi_file_map_t MPI::File::mpi_file_map;
@ -279,55 +279,49 @@ ompi_mpi_cxx_op_intercept(void *invec, void *outvec, int *len,
// Attribute copy functions -- comm, type, and win
//
extern "C" int
ompi_mpi_cxx_comm_copy_attr_intercept(MPI_Comm oldcomm, int keyval,
ompi_mpi_cxx_comm_copy_attr_intercept(MPI_Comm comm, int keyval,
void *extra_state, void *attribute_val_in,
void *attribute_val_out, int *flag)
void *attribute_val_out, int *flag,
MPI_Comm newcomm)
{
int ret = 0;
MPI::Comm::key_pair_t* copy_and_delete;
MPI::Comm::keyval_pair_t* copy_and_delete;
MPI::Comm::Copy_attr_function* copy_fn;
MPI::Comm::comm_pair_t *comm_type;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
copy_and_delete = MPI::Comm::mpi_comm_key_fn_map[keyval];
copy_and_delete = MPI::Comm::mpi_comm_keyval_fn_map[keyval];
copy_fn = copy_and_delete->first;
comm_type = MPI::Comm::mpi_comm_map[oldcomm];
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
// Just in case...
if (comm_type == 0)
return MPI::ERR_OTHER;
MPI::Intracomm intracomm;
MPI::Intercomm intercomm;
MPI::Graphcomm graphcomm;
MPI::Cartcomm cartcomm;
int thetype = (int)comm_type->second;
bool bflag = OPAL_INT_TO_BOOL(*flag);
switch (thetype) {
case eIntracomm:
intracomm = MPI::Intracomm(*comm_type->first);
ret = copy_fn(intracomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
break;
case eIntercomm:
intercomm = MPI::Intercomm(*comm_type->first);
ret = copy_fn(intercomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
break;
case eGraphcomm:
graphcomm = MPI::Graphcomm(*comm_type->first);
ret = copy_fn(graphcomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
break;
case eCartcomm:
cartcomm = MPI::Cartcomm(*comm_type->first);
ret = copy_fn(cartcomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
break;
if (NULL != copy_fn) {
if (OMPI_COMM_IS_GRAPH(comm)) {
graphcomm = MPI::Graphcomm(comm);
ret = copy_fn(graphcomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
} else if (OMPI_COMM_IS_CART(comm)) {
cartcomm = MPI::Cartcomm(comm);
ret = copy_fn(cartcomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
} else if (OMPI_COMM_IS_INTRA(comm)) {
intracomm = MPI::Intracomm(comm);
ret = copy_fn(intracomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
} else if (OMPI_COMM_IS_INTER(comm)) {
intercomm = MPI::Intercomm(comm);
ret = copy_fn(intercomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag);
} else {
ret = MPI::ERR_COMM;
}
} else {
ret = MPI::ERR_OTHER;
}
*flag = (int)bflag;
@ -339,50 +333,39 @@ ompi_mpi_cxx_comm_delete_attr_intercept(MPI_Comm comm, int keyval,
void *attribute_val, void *extra_state)
{
int ret = 0;
MPI::Comm::key_pair_t * copy_and_delete;
MPI::Comm::keyval_pair_t * copy_and_delete;
MPI::Comm::Delete_attr_function* delete_fn;
MPI::Comm::comm_pair_t *comm_type;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
copy_and_delete = MPI::Comm::mpi_comm_key_fn_map[keyval];
copy_and_delete = MPI::Comm::mpi_comm_keyval_fn_map[keyval];
delete_fn = copy_and_delete->second;
comm_type = MPI::Comm::mpi_comm_map[comm];
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
// Just in case...
if (comm_type == 0)
return MPI::ERR_OTHER;
MPI::Intracomm intracomm;
MPI::Intercomm intercomm;
MPI::Graphcomm graphcomm;
MPI::Cartcomm cartcomm;
int thetype = (long)(comm_type->second);
if (NULL != delete_fn) {
if (OMPI_COMM_IS_GRAPH(comm)) {
graphcomm = MPI::Graphcomm(comm);
ret = delete_fn(graphcomm, keyval, attribute_val, extra_state);
} else if (OMPI_COMM_IS_CART(comm)) {
cartcomm = MPI::Cartcomm(comm);
ret = delete_fn(cartcomm, keyval, attribute_val, extra_state);
} else if (OMPI_COMM_IS_INTRA(comm)) {
intracomm = MPI::Intracomm(comm);
ret = delete_fn(intracomm, keyval, attribute_val, extra_state);
} else if (OMPI_COMM_IS_INTER(comm)) {
intercomm = MPI::Intercomm(comm);
ret = delete_fn(intercomm, keyval, attribute_val, extra_state);
} else {
ret = MPI::ERR_COMM;
}
} else {
ret = MPI::ERR_OTHER;
}
if (delete_fn > (MPI::Comm::Delete_attr_function*) 100) {
switch (thetype) {
case eIntracomm:
intracomm = MPI::Intracomm(*comm_type->first);
ret = delete_fn(intracomm, keyval, attribute_val, extra_state);
break;
case eIntercomm:
intercomm = MPI::Intercomm(*comm_type->first);
ret = delete_fn(intercomm, keyval, attribute_val, extra_state);
break;
case eGraphcomm:
graphcomm = MPI::Graphcomm(*comm_type->first);
ret = delete_fn(graphcomm, keyval, attribute_val, extra_state);
break;
case eCartcomm:
cartcomm = MPI::Cartcomm(*comm_type->first);
ret = delete_fn(cartcomm, keyval, attribute_val, extra_state);
break;
}
} else
ret = MPI::ERR_OTHER;
return ret;
}
@ -394,13 +377,13 @@ ompi_mpi_cxx_type_copy_attr_intercept(MPI_Datatype oldtype, int keyval,
{
int ret = 0;
MPI::Datatype::key_pair_t* copy_and_delete;
MPI::Datatype::keyval_pair_t* copy_and_delete;
MPI::Datatype::Copy_attr_function* copy_fn;
MPI::Datatype *cxx_oldtype;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_oldtype = MPI::Datatype::mpi_type_map[oldtype];
copy_and_delete = MPI::Datatype::mpi_type_key_fn_map[keyval];
copy_and_delete = MPI::Datatype::mpi_type_keyval_fn_map[keyval];
copy_fn = copy_and_delete->first;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
@ -419,13 +402,13 @@ ompi_mpi_cxx_type_delete_attr_intercept(MPI_Datatype type, int keyval,
{
int ret = 0;
MPI::Datatype::key_pair_t* copy_and_delete;
MPI::Datatype::keyval_pair_t* copy_and_delete;
MPI::Datatype::Delete_attr_function* delete_fn;
MPI::Datatype *cxx_type;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_type = MPI::Datatype::mpi_type_map[type];
copy_and_delete = MPI::Datatype::mpi_type_key_fn_map[keyval];
copy_and_delete = MPI::Datatype::mpi_type_keyval_fn_map[keyval];
delete_fn = copy_and_delete->second;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
@ -440,13 +423,13 @@ ompi_mpi_cxx_win_copy_attr_intercept(MPI_Win oldwin, int keyval,
{
int ret = 0;
MPI::Win::key_pair_t* copy_and_delete;
MPI::Win::keyval_pair_t* copy_and_delete;
MPI::Win::Copy_attr_function* copy_fn;
MPI::Win *cxx_oldwin;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_oldwin = MPI::Win::mpi_win_map[oldwin];
copy_and_delete = MPI::Win::mpi_win_key_fn_map[keyval];
copy_and_delete = MPI::Win::mpi_win_keyval_fn_map[keyval];
copy_fn = copy_and_delete->first;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
@ -465,13 +448,13 @@ ompi_mpi_cxx_win_delete_attr_intercept(MPI_Win win, int keyval,
{
int ret = 0;
MPI::Win::key_pair_t* copy_and_delete;
MPI::Win::keyval_pair_t* copy_and_delete;
MPI::Win::Delete_attr_function* delete_fn;
MPI::Win *cxx_win;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_win = MPI::Win::mpi_win_map[win];
copy_and_delete = MPI::Win::mpi_win_key_fn_map[keyval];
copy_and_delete = MPI::Win::mpi_win_keyval_fn_map[keyval];
delete_fn = copy_and_delete->second;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);

Просмотреть файл

@ -10,7 +10,7 @@
// University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
// Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -84,7 +84,8 @@ enum CommType { eIntracomm, eIntercomm, eCartcomm, eGraphcomm};
extern "C" int
ompi_mpi_cxx_comm_copy_attr_intercept(MPI_Comm oldcomm, int keyval,
void *extra_state, void *attribute_val_in,
void *attribute_val_out, int *flag);
void *attribute_val_out, int *flag,
MPI_Comm newcomm);
extern "C" int
ompi_mpi_cxx_comm_delete_attr_intercept(MPI_Comm comm, int keyval,
void *attribute_val, void *extra_state);

Просмотреть файл

@ -3,6 +3,7 @@
// Copyright (c) 2006 Los Alamos National Security, LLC. All rights
// reserved.
// Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -15,6 +16,12 @@
#include "ompi/mpi/cxx/mpicxx.h"
#include "opal/threads/mutex.h"
#include "ompi/communicator/communicator.h"
#include "ompi/attribute/attribute.h"
#include "ompi/errhandler/errhandler.h"
static void cxx_win_keyval_destructor(int keyval);
void
MPI::Win::Free()
@ -37,92 +44,84 @@ MPI::Win::Set_errhandler(const MPI::Errhandler& errhandler)
(void)MPI_Win_set_errhandler(mpi_win, errhandler);
}
// 1) original Create_keyval that takes the first 2 arguments as C++ macros
int
MPI::Win::Create_keyval(MPI::Win::Copy_attr_function* win_copy_attr_fn,
MPI::Win::Delete_attr_function* win_delete_attr_fn,
void* extra_state)
MPI::Win::do_create_keyval(MPI_Win_copy_attr_function* c_copy_fn,
MPI_Win_delete_attr_function* c_delete_fn,
Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state)
{
int keyval;
(void) MPI_Win_create_keyval(ompi_mpi_cxx_win_copy_attr_intercept,
ompi_mpi_cxx_win_delete_attr_intercept,
&keyval, extra_state);
key_pair_t* copy_and_delete =
new key_pair_t(win_copy_attr_fn, win_delete_attr_fn);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Win::mpi_win_key_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
// 2) overload Create_keyval to take the first 2 arguments as C macros
int
MPI::Win::Create_keyval(MPI_Win_copy_attr_function* win_copy_attr_fn,
MPI_Win_delete_attr_function* win_delete_attr_fn,
void* extra_state)
{
int keyval;
(void) MPI_Win_create_keyval(win_copy_attr_fn,
win_delete_attr_fn,
&keyval, extra_state);
return keyval;
}
// 3) overload Create_keyval to take the first 2 arguments as C++ & C macros
int
MPI::Win::Create_keyval(MPI::Win::Copy_attr_function* win_copy_attr_fn,
MPI_Win_delete_attr_function* win_delete_attr_fn,
void* extra_state)
{
int keyval;
// use a dummy attr_fn to create the c++ key pair
MPI::Win::Delete_attr_function* dummy_win_delete_attr_fn = NULL;
(void) MPI_Win_create_keyval(ompi_mpi_cxx_win_copy_attr_intercept,
win_delete_attr_fn,
&keyval, extra_state);
key_pair_t* copy_and_delete =
new key_pair_t(win_copy_attr_fn, dummy_win_delete_attr_fn);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Win::mpi_win_key_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
// 4) overload Create_keyval to take the first 2 arguments as C & C++ macros
int
MPI::Win::Create_keyval(MPI_Win_copy_attr_function* win_copy_attr_fn,
MPI::Win::Delete_attr_function* win_delete_attr_fn,
void* extra_state)
{
int keyval;
// use a dummy attr_fn to create the c++ key pair
MPI::Win::Copy_attr_function* dummy_win_copy_attr_fn = NULL;
(void) MPI_Win_create_keyval(win_copy_attr_fn,
ompi_mpi_cxx_win_delete_attr_intercept,
&keyval, extra_state);
key_pair_t* copy_and_delete =
new key_pair_t(dummy_win_copy_attr_fn, win_delete_attr_fn);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Win::mpi_win_key_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
int keyval, ret, count = 0;
ompi_attribute_fn_ptr_union_t copy_fn;
ompi_attribute_fn_ptr_union_t delete_fn;
Copy_attr_function *cxx_pair_copy = NULL;
Delete_attr_function *cxx_pair_delete = NULL;
// We do not call MPI_Win_create_keyval() here because we need to
// pass in a special destructor to the backend keyval creation
// that gets invoked when the keyval's reference count goes to 0
// and is finally destroyed (i.e., clean up some caching/lookup
// data here in the C++ bindings layer). This destructor is
// *only* used in the C++ bindings, so it's not set by the C
// MPI_Win_create_keyval(). Hence, we do all the work here (and
// ensure to set the destructor atomicly when the keyval is
// created).
// Error check. Must have exactly 2 non-NULL function pointers.
if (NULL != c_copy_fn) {
copy_fn.attr_win_copy_fn =
(MPI_Win_internal_copy_attr_function*) c_copy_fn;
++count;
}
if (NULL != c_delete_fn) {
delete_fn.attr_win_delete_fn = c_delete_fn;
++count;
}
if (NULL != cxx_copy_fn) {
copy_fn.attr_win_copy_fn =
(MPI_Win_internal_copy_attr_function*) ompi_mpi_cxx_win_copy_attr_intercept;
cxx_pair_copy = cxx_copy_fn;
++count;
}
if (NULL != cxx_delete_fn) {
delete_fn.attr_win_delete_fn =
ompi_mpi_cxx_win_delete_attr_intercept;
cxx_pair_delete = cxx_delete_fn;
++count;
}
if (2 != count) {
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG,
"MPI::Win::Create_keyval");
}
ret = ompi_attr_create_keyval(WIN_ATTR, copy_fn, delete_fn,
&keyval, extra_state, 0,
cxx_win_keyval_destructor);
if (OMPI_SUCCESS != ret) {
return ret;
}
keyval_pair_t* copy_and_delete =
new keyval_pair_t(cxx_pair_copy, cxx_pair_delete);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Win::mpi_win_keyval_fn_map[keyval] = copy_and_delete;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval;
}
void
MPI::Win::Free_keyval(int& win_keyval)
// This function is called back out of the keyval destructor in the C
// layer when the keyval is not be used by any attributes anymore,
// anywhere. So we can definitely safely remove the entry for this
// keyval from the C++ map.
static void cxx_win_keyval_destructor(int keyval)
{
int save = win_keyval;
(void) MPI_Win_free_keyval(&win_keyval);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
MPI::Win::mpi_win_key_fn_map.erase(save);
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Win::mpi_win_keyval_fn_map.end() !=
MPI::Win::mpi_win_keyval_fn_map.find(keyval) &&
NULL != MPI::Win::mpi_win_keyval_fn_map[keyval]) {
delete MPI::Win::mpi_win_keyval_fn_map[keyval];
MPI::Win::mpi_win_keyval_fn_map.erase(keyval);
}
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
}
void
MPI::Win::Set_attr(int win_keyval, const void* attribute_val)
{
(void) MPI_Win_set_attr(mpi_win, win_keyval, const_cast<void *>(attribute_val));
OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Win::mpi_win_map[mpi_win] == 0) {
MPI::Win::mpi_win_map[mpi_win] = (Win*) this;
}
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
}

Просмотреть файл

@ -10,7 +10,7 @@
// University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
// Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
// $COPYRIGHT$
//
@ -143,6 +143,9 @@ public:
//
virtual void Call_errhandler(int errorcode) const;
// Need 4 overloaded versions of this function because per the
// MPI-2 spec, you can mix-n-match the C predefined functions with
// C++ functions.
static int Create_keyval(Copy_attr_function* win_copy_attr_fn,
Delete_attr_function* win_delete_attr_fn,
void* extra_state);
@ -156,6 +159,14 @@ public:
Delete_attr_function* win_delete_attr_fn,
void* extra_state);
protected:
static int do_create_keyval(MPI_Win_copy_attr_function* c_copy_fn,
MPI_Win_delete_attr_function* c_delete_fn,
Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state);
public:
virtual void Delete_attr(int win_keyval);
static void Free_keyval(int& win_keyval);
@ -178,9 +189,9 @@ public:
typedef ::std::map<MPI_Win, Win*> mpi_win_map_t;
static mpi_win_map_t mpi_win_map;
typedef ::std::pair<Win::Copy_attr_function*, Win::Delete_attr_function*> key_pair_t;
typedef ::std::map<int, key_pair_t*> mpi_win_key_fn_map_t;
static mpi_win_key_fn_map_t mpi_win_key_fn_map;
typedef ::std::pair<Win::Copy_attr_function*, Win::Delete_attr_function*> keyval_pair_t;
typedef ::std::map<int, keyval_pair_t*> mpi_win_keyval_fn_map_t;
static mpi_win_keyval_fn_map_t mpi_win_keyval_fn_map;
protected:
#if 0 /* OMPI_ENABLE_MPI_PROFILING */

Просмотреть файл

@ -11,6 +11,7 @@
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
// Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
@ -181,6 +182,58 @@ MPI::Win::Call_errhandler(int errorcode) const
}
// 1) original Create_keyval that takes the first 2 arguments as C++
// functions
inline int
MPI::Win::Create_keyval(MPI::Win::Copy_attr_function* win_copy_attr_fn,
MPI::Win::Delete_attr_function* win_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(NULL, NULL,
win_copy_attr_fn, win_delete_attr_fn,
extra_state);
}
// 2) overload Create_keyval to take the first 2 arguments as C
// functions
inline int
MPI::Win::Create_keyval(MPI_Win_copy_attr_function* win_copy_attr_fn,
MPI_Win_delete_attr_function* win_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(win_copy_attr_fn, win_delete_attr_fn,
NULL, NULL,
extra_state);
}
// 3) overload Create_keyval to take the first 2 arguments as C++ & C
// functions
inline int
MPI::Win::Create_keyval(MPI::Win::Copy_attr_function* win_copy_attr_fn,
MPI_Win_delete_attr_function* win_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(NULL, win_delete_attr_fn,
win_copy_attr_fn, NULL,
extra_state);
}
// 4) overload Create_keyval to take the first 2 arguments as C & C++
// functions
inline int
MPI::Win::Create_keyval(MPI_Win_copy_attr_function* win_copy_attr_fn,
MPI::Win::Delete_attr_function* win_delete_attr_fn,
void* extra_state)
{
// Back-end function does the heavy lifting
return do_create_keyval(win_copy_attr_fn, NULL,
NULL, win_delete_attr_fn,
extra_state);
}
inline void
MPI::Win::Delete_attr(int win_keyval)
{
@ -188,6 +241,13 @@ MPI::Win::Delete_attr(int win_keyval)
}
inline void
MPI::Win::Free_keyval(int& win_keyval)
{
(void) MPI_Win_free_keyval(&win_keyval);
}
// version 1: pre-errata Get_attr (not correct, but probably nice to support
inline bool
MPI::Win::Get_attr(const Win& win, int win_keyval,
@ -216,6 +276,12 @@ MPI::Win::Get_name(char* win_name, int& resultlen) const
}
inline void
MPI::Win::Set_attr(int win_keyval, const void* attribute_val)
{
(void) MPI_Win_set_attr(mpi_win, win_keyval, const_cast<void *>(attribute_val));
}
inline void
MPI::Win::Set_name(const char* win_name)

Просмотреть файл

@ -79,7 +79,8 @@ void mpi_comm_create_keyval_f(ompi_mpi2_fortran_copy_attr_function* comm_copy_at
to the old MPI-1 INTEGER-parameter functions). */
ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn, del_fn,
comm_keyval, extra_state, OMPI_KEYVAL_F77);
comm_keyval, extra_state, OMPI_KEYVAL_F77,
NULL);
if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD,

Просмотреть файл

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -79,7 +80,8 @@ void mpi_keyval_create_f(ompi_mpi1_fortran_copy_attr_function* copy_attr_fn,
ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn, del_fn,
keyval, extra_state,
OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_MPI1);
OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_MPI1,
NULL);
if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD,

Просмотреть файл

@ -76,7 +76,8 @@ void mpi_type_create_keyval_f(ompi_mpi2_fortran_copy_attr_function* type_copy_at
to the old MPI-1 INTEGER-parameter functions). */
ret = ompi_attr_create_keyval(TYPE_ATTR, copy_fn, del_fn,
type_keyval, extra_state, OMPI_KEYVAL_F77);
type_keyval, extra_state, OMPI_KEYVAL_F77,
NULL);
if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD,

Просмотреть файл

@ -78,7 +78,8 @@ void mpi_win_create_keyval_f(ompi_mpi2_fortran_copy_attr_function* win_copy_attr
to the old MPI-1 INTEGER-parameter functions). */
ret = ompi_attr_create_keyval(WIN_ATTR, copy_fn, del_fn,
win_keyval, extra_state, OMPI_KEYVAL_F77);
win_keyval, extra_state, OMPI_KEYVAL_F77,
NULL);
if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER,