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

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

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved. * University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California. * Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved. * All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$ * $COPYRIGHT$
* *
* Additional copyrights may follow * 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 *, typedef int (MPI_Win_internal_copy_attr_function)(MPI_Win, int, void *,
void *, void *, int *, MPI_Win); 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 /* Union to take care of proper casting of the function pointers
passed from the front end functions depending on the type. This passed from the front end functions depending on the type. This
will avoid casting function pointers to void* */ 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; 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; opal_object_t super;
ompi_attribute_type_t attr_type; /**< One of COMM/WIN/DTYPE. This ompi_attribute_type_t attr_type; /**< One of COMM/WIN/DTYPE. This
will be used to cast the will be used to cast the
@ -160,9 +163,13 @@ struct ompi_attrkey_item_t {
void *extra_state; /**< Extra state of the attribute */ void *extra_state; /**< Extra state of the attribute */
int key; /**< Keep a track of which key this item belongs to, so that int key; /**< Keep a track of which key this item belongs to, so that
the key can be deleted when this object is destroyed */ 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 */ /* Functions */
@ -174,14 +181,14 @@ typedef struct ompi_attrkey_item_t ompi_attrkey_item_t;
*/ */
static inline 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); *hash = OBJ_NEW(opal_hash_table_t);
if (NULL == keyhash) { if (NULL == hash) {
fprintf(stderr, "Error while creating the local attribute list\n"); fprintf(stderr, "Error while creating the local attribute list\n");
return MPI_ERR_SYSRESOURCE; 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; 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 * @return OMPI return code
*/ */
@ -197,7 +204,7 @@ int ompi_attr_hash_init(opal_hash_table_t **keyhash)
int ompi_attr_init(void); 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); int ompi_attr_finalize(void);
@ -234,9 +241,10 @@ int ompi_attr_finalize(void);
*/ */
int ompi_attr_create_keyval(ompi_attribute_type_t type, 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 copy_attr_fn,
ompi_attribute_fn_ptr_union_t delete_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);
/** /**
* Free an attribute keyval * 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 type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (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 key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN) * @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (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 * @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code * @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. * initialized.
* *
* Note that need_lock should *always* be true when this function is * 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. * (read: better) this way.
*/ */
int ompi_attr_set_c(ompi_attribute_type_t type, void *object, 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); 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 type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (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 key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN) * @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (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 * @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code * @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. * initialized.
* *
* Note that need_lock should *always* be true when this function is * 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. * (read: better) this way.
*/ */
int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object, 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, int key, MPI_Fint attribute,
bool predefined, bool need_lock); 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 type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (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 key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (IN) * @param attribute The actual attribute pointer (IN)
* @param predefined Whether the key is predefined or not 0/1 (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 * @param need_lock Whether we need to need to lock the keyval_lock or not
* @return OMPI error code * @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. * initialized.
* *
* Note that need_lock should *always* be true when this function is * 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. * (read: better) this way.
*/ */
int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object, 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, int key, MPI_Aint attribute,
bool predefined, bool need_lock); bool predefined, bool need_lock);
/** /**
* Get an attribute on the comm/win/datatype in a form valid for C. * 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 key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT) * @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated * @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. * (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); 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 * Get an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-1. * 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 key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT) * @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated * @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. * (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); 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 * Get an attribute on the comm/win/datatype in a form valid for
* Fortran MPI-2. * 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 key Key val for the attribute (IN)
* @param attribute The actual attribute pointer (OUT) * @param attribute The actual attribute pointer (OUT)
* @param flag Flag whether an attribute is associated * @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. * (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); 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 * Delete an attribute on the comm/win/datatype
* @param type Type of attribute (COMM/WIN/DTYPE) (IN) * @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The actual Comm/Win/Datatype object (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 key Key val for the attribute (IN)
* @param predefined Whether the key is predefined or not 0/1 (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 * @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, 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); 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 type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param old_object The old COMM/WIN/DTYPE object (IN) * @param old_object The old COMM/WIN/DTYPE object (IN)
* @param new_object The new 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 attr_hash The attribute hash table hanging on old object(IN)
* @param newkeyhash The attribute hash table hanging on new object(IN) * @param newattr_hash The attribute hash table hanging on new object(IN)
* @return OMPI error code * @return OMPI error code
* *
*/ */
int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object, 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); 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 * object in one shot
* @param type Type of attribute (COMM/WIN/DTYPE) (IN) * @param type Type of attribute (COMM/WIN/DTYPE) (IN)
* @param object The COMM/WIN/DTYPE object (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 * @return OMPI error code
* *
*/ */
int ompi_attr_delete_all(ompi_attribute_type_t type, void *object, 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. * Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved. * All rights reserved.
* Copyright (c) 2006 University of Houston. All rights reserved. * Copyright (c) 2006 University of Houston. All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$ * $COPYRIGHT$
* *
* Additional copyrights may follow * 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); (want_inherit ? MPI_COMM_DUP_FN : MPI_COMM_NULL_COPY_FN);
del.attr_communicator_delete_fn = MPI_COMM_NULL_DELETE_FN; del.attr_communicator_delete_fn = MPI_COMM_NULL_DELETE_FN;
err = ompi_attr_create_keyval(COMM_ATTR, copy, del, err = ompi_attr_create_keyval(COMM_ATTR, copy, del,
&keyval, NULL, OMPI_KEYVAL_PREDEFINED); &keyval, NULL, OMPI_KEYVAL_PREDEFINED, NULL);
if (MPI_SUCCESS != err) { if (MPI_SUCCESS != err) {
return 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; 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; del.attr_win_delete_fn = MPI_WIN_NULL_DELETE_FN;
err = ompi_attr_create_keyval(WIN_ATTR, copy, del, err = ompi_attr_create_keyval(WIN_ATTR, copy, del,
&keyval, NULL, OMPI_KEYVAL_PREDEFINED); &keyval, NULL, OMPI_KEYVAL_PREDEFINED, NULL);
if (MPI_SUCCESS != err) { if (MPI_SUCCESS != err) {
return err; return err;
} }

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

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved. * University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California. * Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved. * All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$ * $COPYRIGHT$
* *
* Additional copyrights may follow * 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; del_fn.attr_communicator_delete_fn = comm_delete_attr_fn;
ret = ompi_attr_create_keyval(COMM_ATTR, copy_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); OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME);
} }

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

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved. * University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California. * Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved. * All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$ * $COPYRIGHT$
* *
* Additional copyrights may follow * 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; del_fn.attr_communicator_delete_fn = delete_attr_fn;
ret = ompi_attr_create_keyval(COMM_ATTR, copy_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); OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME);
} }

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

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved. * University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California. * Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved. * All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$ * $COPYRIGHT$
* *
* Additional copyrights may follow * 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; del_fn.attr_datatype_delete_fn = type_delete_attr_fn;
ret = ompi_attr_create_keyval(TYPE_ATTR, copy_fn, del_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); OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, ret, FUNC_NAME);
} }

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

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved. * University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California. * Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved. * All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$ * $COPYRIGHT$
* *
* Additional copyrights may follow * 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; del_fn.attr_win_delete_fn = win_delete_attr_fn;
ret = ompi_attr_create_keyval(WIN_ATTR, copy_fn, del_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); OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD, MPI_ERR_OTHER, FUNC_NAME);
} }

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

@ -10,6 +10,7 @@
// University of Stuttgart. All rights reserved. // University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California. // Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved. // All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$ // $COPYRIGHT$
// //
// Additional copyrights may follow // Additional copyrights may follow
@ -22,6 +23,12 @@
#include "ompi/mpi/cxx/mpicxx.h" #include "ompi/mpi/cxx/mpicxx.h"
#include "opal/threads/mutex.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 // 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 // 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 void
MPI::Comm::Set_errhandler(const MPI::Errhandler& errhandler) 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 //JGS I took the const out because it causes problems when trying to
//call this function with the predefined NULL_COPY_FN etc. //call this function with the predefined NULL_COPY_FN etc.
int int
MPI::Comm::Create_keyval(MPI::Comm::_MPI2CPP_COPYATTRFN_* comm_copy_attr_fn, MPI::Comm::do_create_keyval(MPI_Comm_copy_attr_function* c_copy_fn,
MPI::Comm::_MPI2CPP_DELETEATTRFN_* comm_delete_attr_fn, MPI_Comm_delete_attr_function* c_delete_fn,
void* extra_state) Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state)
{ {
int keyval; int keyval, ret, count = 0;
(void)MPI_Keyval_create(ompi_mpi_cxx_comm_copy_attr_intercept, ompi_attribute_fn_ptr_union_t copy_fn;
ompi_mpi_cxx_comm_delete_attr_intercept, ompi_attribute_fn_ptr_union_t delete_fn;
&keyval, extra_state); Copy_attr_function *cxx_pair_copy = NULL;
key_pair_t* copy_and_delete = Delete_attr_function *cxx_pair_delete = NULL;
new key_pair_t(comm_copy_attr_fn, comm_delete_attr_fn);
// 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); 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); OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
return keyval; return keyval;
} }
// This function is called back out of the keyval destructor in the C
void // layer when the keyval is not be used by any attributes anymore,
MPI::Comm::Free_keyval(int& comm_keyval) // 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); OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
if (MPI::Comm::mpi_comm_key_fn_map[save] != 0) if (MPI::Comm::mpi_comm_keyval_fn_map.end() !=
delete MPI::Comm::mpi_comm_key_fn_map[save]; MPI::Comm::mpi_comm_keyval_fn_map.find(keyval) &&
MPI::Comm::mpi_comm_key_fn_map.erase(save); 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); 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. // University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California. // Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved. // All rights reserved.
// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. // Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$ // $COPYRIGHT$
// //
// Additional copyrights may follow // Additional copyrights may follow
@ -391,12 +391,31 @@ public:
// Keys and Attributes // Keys and Attributes
// //
//JGS I took the const out because it causes problems when trying to // Need 4 overloaded versions of this function because per the
//call this function with the predefined NULL_COPY_FN etc. // 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, static int Create_keyval(Copy_attr_function* comm_copy_attr_fn,
Delete_attr_function* comm_delete_attr_fn, Delete_attr_function* comm_delete_attr_fn,
void* extra_state); 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); static void Free_keyval(int& comm_keyval);
virtual void Set_attr(int comm_keyval, const void* attribute_val) const; 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; 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; typedef ::std::map<MPI_Comm, Comm*> mpi_comm_err_map_t;
static mpi_comm_err_map_t mpi_comm_err_map; static mpi_comm_err_map_t mpi_comm_err_map;
typedef ::std::pair<Comm::_MPI2CPP_COPYATTRFN_*, Comm::_MPI2CPP_DELETEATTRFN_*> key_pair_t; typedef ::std::pair<Comm::_MPI2CPP_COPYATTRFN_*, Comm::_MPI2CPP_DELETEATTRFN_*> keyval_pair_t;
typedef ::std::map<int, key_pair_t*> mpi_comm_key_fn_map_t; typedef ::std::map<int, keyval_pair_t*> mpi_comm_keyval_fn_map_t;
static mpi_comm_key_fn_map_t mpi_comm_key_fn_map; static mpi_comm_keyval_fn_map_t mpi_comm_keyval_fn_map;
void init() { void init() {
my_errhandler = (Errhandler*)0; my_errhandler = (Errhandler*)0;

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

@ -10,6 +10,7 @@
// University of Stuttgart. All rights reserved. // University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California. // Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved. // All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$ // $COPYRIGHT$
// //
// Additional copyrights may follow // Additional copyrights may follow
@ -283,7 +284,12 @@ MPI::Comm::Compare(const MPI::Comm & comm1,
return result; return result;
} }
inline void
MPI::Comm::Free(void)
{
(void)MPI_Comm_free(&mpi_comm);
}
inline bool inline bool
MPI::Comm::Is_inter() const MPI::Comm::Is_inter() const
{ {
@ -546,6 +552,70 @@ MPI::Comm::Create_errhandler(MPI::Comm::_MPI2CPP_ERRHANDLERFN_* function)
return temp; 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 inline bool
MPI::Comm::Get_attr(int comm_keyval, void* attribute_val) const 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 // Copyright (c) 2006 Los Alamos National Security, LLC. All rights
// reserved. // reserved.
// Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. // Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$ // $COPYRIGHT$
// //
// Additional copyrights may follow // Additional copyrights may follow
@ -15,6 +16,11 @@
#include "ompi/mpi/cxx/mpicxx.h" #include "ompi/mpi/cxx/mpicxx.h"
#include "opal/threads/mutex.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 void
MPI::Datatype::Free() MPI::Datatype::Free()
@ -28,95 +34,85 @@ MPI::Datatype::Free()
} }
// 1) original Create_keyval that takes the first 2 arguments as C++ macros
int int
MPI::Datatype::Create_keyval(MPI::Datatype::Copy_attr_function* type_copy_attr_fn, MPI::Datatype::do_create_keyval(MPI_Type_copy_attr_function* c_copy_fn,
MPI::Datatype::Delete_attr_function* type_delete_attr_fn, MPI_Type_delete_attr_function* c_delete_fn,
void* extra_state) Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state)
{ {
int keyval; int keyval, ret, count = 0;
(void) MPI_Type_create_keyval(ompi_mpi_cxx_type_copy_attr_intercept, ompi_attribute_fn_ptr_union_t copy_fn;
ompi_mpi_cxx_type_delete_attr_intercept, ompi_attribute_fn_ptr_union_t delete_fn;
&keyval, extra_state); Copy_attr_function *cxx_pair_copy = NULL;
key_pair_t* copy_and_delete = Delete_attr_function *cxx_pair_delete = NULL;
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;
}
// 2) overload Create_keyval to take the first 2 arguments as C macros // We do not call MPI_Type_create_keyval() here because we need to
int // pass in a special destructor to the backend keyval creation
MPI::Datatype::Create_keyval(MPI_Type_copy_attr_function* type_copy_attr_fn, // that gets invoked when the keyval's reference count goes to 0
MPI_Type_delete_attr_function* type_delete_attr_fn, // and is finally destroyed (i.e., clean up some caching/lookup
void* extra_state) // data here in the C++ bindings layer). This destructor is
{ // *only* used in the C++ bindings, so it's not set by the C
int keyval; // MPI_Type_create_keyval(). Hence, we do all the work here (and
(void) MPI_Type_create_keyval(type_copy_attr_fn, // ensure to set the destructor atomicly when the keyval is
type_delete_attr_fn, // created).
&keyval, extra_state);
return keyval;
}
// 3) overload Create_keyval to take the first 2 arguments as C++ & C macros // Error check. Must have exactly 2 non-NULL function pointers.
int if (NULL != c_copy_fn) {
MPI::Datatype::Create_keyval(MPI::Datatype::Copy_attr_function* type_copy_attr_fn, copy_fn.attr_datatype_copy_fn =
MPI_Type_delete_attr_function* type_delete_attr_fn, (MPI_Type_internal_copy_attr_function*) c_copy_fn;
void* extra_state) ++count;
{ }
int keyval; if (NULL != c_delete_fn) {
// use a dummy attr_fn to create the c++ key pair delete_fn.attr_datatype_delete_fn = c_delete_fn;
MPI::Datatype::Delete_attr_function* dummy_type_delete_attr_fn = NULL; ++count;
(void) MPI_Type_create_keyval(ompi_mpi_cxx_type_copy_attr_intercept, }
type_delete_attr_fn, if (NULL != cxx_copy_fn) {
&keyval, extra_state); copy_fn.attr_datatype_copy_fn =
key_pair_t* copy_and_delete = (MPI_Type_internal_copy_attr_function*) ompi_mpi_cxx_type_copy_attr_intercept;
new key_pair_t(type_copy_attr_fn, dummy_type_delete_attr_fn); cxx_pair_copy = cxx_copy_fn;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); ++count;
MPI::Datatype::mpi_type_key_fn_map[keyval] = copy_and_delete; }
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex); if (NULL != cxx_delete_fn) {
return keyval; 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 ret = ompi_attr_create_keyval(TYPE_ATTR, copy_fn, delete_fn,
int &keyval, extra_state, 0,
MPI::Datatype::Create_keyval(MPI_Type_copy_attr_function* type_copy_attr_fn, cxx_type_keyval_destructor);
MPI::Datatype::Delete_attr_function* type_delete_attr_fn, if (OMPI_SUCCESS != ret) {
void* extra_state) return ret;
{ }
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;
}
void keyval_pair_t* copy_and_delete =
MPI::Datatype::Free_keyval(int& type_keyval) new keyval_pair_t(cxx_pair_copy, cxx_pair_delete);
{
int save = type_keyval;
(void) MPI_Type_free_keyval(&type_keyval);
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); 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); 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. // Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved. // All rights reserved.
// Copyright (c) 2006-2007 Sun Microsystems, Inc. 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$ // $COPYRIGHT$
// //
// Additional copyrights may follow // Additional copyrights may follow
@ -161,7 +161,10 @@ public:
// //
virtual Datatype Dup() const; 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, static int Create_keyval(Copy_attr_function* type_copy_attr_fn,
Delete_attr_function* type_delete_attr_fn, Delete_attr_function* type_delete_attr_fn,
void* extra_state); void* extra_state);
@ -175,6 +178,17 @@ public:
Delete_attr_function* type_delete_attr_fn, Delete_attr_function* type_delete_attr_fn,
void* extra_state); 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); virtual void Delete_attr(int type_keyval);
static void Free_keyval(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; typedef ::std::map<MPI_Datatype, Datatype*> mpi_type_map_t;
static mpi_type_map_t mpi_type_map; static mpi_type_map_t mpi_type_map;
typedef ::std::pair<Datatype::Copy_attr_function*, Datatype::Delete_attr_function*> key_pair_t; typedef ::std::pair<Datatype::Copy_attr_function*, Datatype::Delete_attr_function*> keyval_pair_t;
typedef ::std::map<int, key_pair_t*> mpi_type_key_fn_map_t; typedef ::std::map<int, keyval_pair_t*> mpi_type_keyval_fn_map_t;
static mpi_type_key_fn_map_t mpi_type_key_fn_map; 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 inline void
MPI::Datatype::Delete_attr(int type_keyval) MPI::Datatype::Delete_attr(int type_keyval)
{ {
(void) MPI_Type_delete_attr(mpi_datatype, 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 inline bool
MPI::Datatype::Get_attr(int type_keyval, 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); (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 inline void
MPI::Datatype::Set_name(const char* type_name) MPI::Datatype::Set_name(const char* type_name)

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

@ -10,7 +10,7 @@
// University of Stuttgart. All rights reserved. // University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California. // Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved. // All rights reserved.
// Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. // Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$ // $COPYRIGHT$
// //
// Additional copyrights may follow // Additional copyrights may follow
@ -24,17 +24,17 @@
#include "ompi_config.h" #include "ompi_config.h"
#include "ompi/errhandler/errhandler.h" #include "ompi/errhandler/errhandler.h"
#include "ompi/communicator/communicator.h"
#include "opal/threads/mutex.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_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_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_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; 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 // Attribute copy functions -- comm, type, and win
// //
extern "C" int 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 *extra_state, void *attribute_val_in,
void *attribute_val_out, int *flag) void *attribute_val_out, int *flag,
MPI_Comm newcomm)
{ {
int ret = 0; 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::Copy_attr_function* copy_fn;
MPI::Comm::comm_pair_t *comm_type;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); 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; copy_fn = copy_and_delete->first;
comm_type = MPI::Comm::mpi_comm_map[oldcomm];
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex); OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
// Just in case...
if (comm_type == 0)
return MPI::ERR_OTHER;
MPI::Intracomm intracomm; MPI::Intracomm intracomm;
MPI::Intercomm intercomm; MPI::Intercomm intercomm;
MPI::Graphcomm graphcomm; MPI::Graphcomm graphcomm;
MPI::Cartcomm cartcomm; MPI::Cartcomm cartcomm;
int thetype = (int)comm_type->second;
bool bflag = OPAL_INT_TO_BOOL(*flag); bool bflag = OPAL_INT_TO_BOOL(*flag);
switch (thetype) { if (NULL != copy_fn) {
case eIntracomm: if (OMPI_COMM_IS_GRAPH(comm)) {
intracomm = MPI::Intracomm(*comm_type->first); graphcomm = MPI::Graphcomm(comm);
ret = copy_fn(intracomm, keyval, extra_state, ret = copy_fn(graphcomm, keyval, extra_state,
attribute_val_in, attribute_val_out, bflag); attribute_val_in, attribute_val_out, bflag);
break; } else if (OMPI_COMM_IS_CART(comm)) {
case eIntercomm: cartcomm = MPI::Cartcomm(comm);
intercomm = MPI::Intercomm(*comm_type->first); ret = copy_fn(cartcomm, keyval, extra_state,
ret = copy_fn(intercomm, keyval, extra_state, attribute_val_in, attribute_val_out, bflag);
attribute_val_in, attribute_val_out, bflag); } else if (OMPI_COMM_IS_INTRA(comm)) {
break; intracomm = MPI::Intracomm(comm);
case eGraphcomm: ret = copy_fn(intracomm, keyval, extra_state,
graphcomm = MPI::Graphcomm(*comm_type->first); attribute_val_in, attribute_val_out, bflag);
ret = copy_fn(graphcomm, keyval, extra_state, } else if (OMPI_COMM_IS_INTER(comm)) {
attribute_val_in, attribute_val_out, bflag); intercomm = MPI::Intercomm(comm);
break; ret = copy_fn(intercomm, keyval, extra_state,
case eCartcomm: attribute_val_in, attribute_val_out, bflag);
cartcomm = MPI::Cartcomm(*comm_type->first); } else {
ret = copy_fn(cartcomm, keyval, extra_state, ret = MPI::ERR_COMM;
attribute_val_in, attribute_val_out, bflag); }
break; } else {
ret = MPI::ERR_OTHER;
} }
*flag = (int)bflag; *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) void *attribute_val, void *extra_state)
{ {
int ret = 0; int ret = 0;
MPI::Comm::keyval_pair_t * copy_and_delete;
MPI::Comm::key_pair_t * copy_and_delete;
MPI::Comm::Delete_attr_function* delete_fn; MPI::Comm::Delete_attr_function* delete_fn;
MPI::Comm::comm_pair_t *comm_type;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); 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; delete_fn = copy_and_delete->second;
comm_type = MPI::Comm::mpi_comm_map[comm];
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex); OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);
// Just in case...
if (comm_type == 0)
return MPI::ERR_OTHER;
MPI::Intracomm intracomm; MPI::Intracomm intracomm;
MPI::Intercomm intercomm; MPI::Intercomm intercomm;
MPI::Graphcomm graphcomm; MPI::Graphcomm graphcomm;
MPI::Cartcomm cartcomm; 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; return ret;
} }
@ -394,13 +377,13 @@ ompi_mpi_cxx_type_copy_attr_intercept(MPI_Datatype oldtype, int keyval,
{ {
int ret = 0; 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::Copy_attr_function* copy_fn;
MPI::Datatype *cxx_oldtype; MPI::Datatype *cxx_oldtype;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_oldtype = MPI::Datatype::mpi_type_map[oldtype]; 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; copy_fn = copy_and_delete->first;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex); 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; 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::Delete_attr_function* delete_fn;
MPI::Datatype *cxx_type; MPI::Datatype *cxx_type;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_type = MPI::Datatype::mpi_type_map[type]; 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; delete_fn = copy_and_delete->second;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex); 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; 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::Copy_attr_function* copy_fn;
MPI::Win *cxx_oldwin; MPI::Win *cxx_oldwin;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_oldwin = MPI::Win::mpi_win_map[oldwin]; 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; copy_fn = copy_and_delete->first;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex); 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; 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::Delete_attr_function* delete_fn;
MPI::Win *cxx_win; MPI::Win *cxx_win;
OPAL_THREAD_LOCK(MPI::mpi_map_mutex); OPAL_THREAD_LOCK(MPI::mpi_map_mutex);
cxx_win = MPI::Win::mpi_win_map[win]; 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; delete_fn = copy_and_delete->second;
OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex); OPAL_THREAD_UNLOCK(MPI::mpi_map_mutex);

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

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

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

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

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

@ -11,6 +11,7 @@
// Copyright (c) 2004-2005 The Regents of the University of California. // Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved. // All rights reserved.
// Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. // Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
// Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$ // $COPYRIGHT$
// //
// Additional copyrights may follow // 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 inline void
MPI::Win::Delete_attr(int win_keyval) 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 // version 1: pre-errata Get_attr (not correct, but probably nice to support
inline bool inline bool
MPI::Win::Get_attr(const Win& win, int win_keyval, 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 inline void
MPI::Win::Set_name(const char* win_name) 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). */ to the old MPI-1 INTEGER-parameter functions). */
ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn, del_fn, 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) { if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD,

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

@ -9,6 +9,7 @@
* University of Stuttgart. All rights reserved. * University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California. * Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved. * All rights reserved.
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$ * $COPYRIGHT$
* *
* Additional copyrights may follow * 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, ret = ompi_attr_create_keyval(COMM_ATTR, copy_fn, del_fn,
keyval, extra_state, keyval, extra_state,
OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_MPI1); OMPI_KEYVAL_F77 | OMPI_KEYVAL_F77_MPI1,
NULL);
if (MPI_SUCCESS != ret) { if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, 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). */ to the old MPI-1 INTEGER-parameter functions). */
ret = ompi_attr_create_keyval(TYPE_ATTR, copy_fn, del_fn, 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) { if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, 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). */ to the old MPI-1 INTEGER-parameter functions). */
ret = ompi_attr_create_keyval(WIN_ATTR, copy_fn, del_fn, 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) { if (MPI_SUCCESS != ret) {
c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER, c_err = OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_OTHER,