Get rid of some xbt_dicts as well.
#define MPI_REQUEST_NULL ((MPI_Request)NULL)
#define MPI_FORTRAN_REQUEST_NULL -1
+typedef int MPI_Copy_function(MPI_Comm oldcomm, int keyval, void* extra_state, void* attribute_val_in,
+ void* attribute_val_out, int* flag);
+typedef int MPI_Delete_function(MPI_Comm comm, int keyval, void* attribute_val, void* extra_state);
+#define MPI_Comm_copy_attr_function MPI_Copy_function
+#define MPI_Comm_delete_attr_function MPI_Delete_function
+typedef int MPI_Type_copy_attr_function(MPI_Datatype type, int keyval, void* extra_state, void* attribute_val_in,
+ void* attribute_val_out, int* flag);
+typedef int MPI_Type_delete_attr_function(MPI_Datatype type, int keyval, void* attribute_val, void* extra_state);
+#define MPI_COMM_NULL_COPY_FN ((MPI_Comm_copy_attr_function*)0)
+#define MPI_COMM_NULL_DELETE_FN ((MPI_Comm_delete_attr_function*)0)
+#define MPI_TYPE_NULL_COPY_FN ((MPI_Type_copy_attr_function*)0)
+#define MPI_TYPE_NULL_DELETE_FN ((MPI_Type_delete_attr_function*)0)
+
+
MPI_CALL(XBT_PUBLIC(int), MPI_Init, (int *argc, char ***argv));
MPI_CALL(XBT_PUBLIC(int), MPI_Finalize, (void));
MPI_CALL(XBT_PUBLIC(int), MPI_Finalized, (int* flag));
typedef void* MPI_Errhandler;
-typedef int MPI_Copy_function(MPI_Comm oldcomm, int keyval, void* extra_state, void* attribute_val_in,
- void* attribute_val_out, int* flag);
-typedef int MPI_Delete_function(MPI_Comm comm, int keyval, void* attribute_val, void* extra_state);
-#define MPI_Comm_copy_attr_function MPI_Copy_function
-#define MPI_Comm_delete_attr_function MPI_Delete_function
-typedef int MPI_Type_copy_attr_function(MPI_Datatype type, int keyval, void* extra_state, void* attribute_val_in,
- void* attribute_val_out, int* flag);
-typedef int MPI_Type_delete_attr_function(MPI_Datatype type, int keyval, void* attribute_val, void* extra_state);
typedef void MPI_Comm_errhandler_function(MPI_Comm *, int *, ...);
typedef int MPI_Grequest_query_function(void *extra_state, MPI_Status *status);
typedef int MPI_Grequest_free_function(void *extra_state);
typedef int MPI_Grequest_cancel_function(void *extra_state, int complete);
#define MPI_DUP_FN MPI_Comm_dup
-#define MPI_COMM_NULL_COPY_FN ((MPI_Comm_copy_attr_function*)0)
-#define MPI_COMM_NULL_DELETE_FN ((MPI_Comm_delete_attr_function*)0)
-#define MPI_COMM_DUP_FN ((MPI_Comm_copy_attr_function *)MPI_DUP_FN)
-#define MPI_TYPE_NULL_COPY_FN ((MPI_Type_copy_attr_function*)0)
-#define MPI_TYPE_NULL_DELETE_FN ((MPI_Type_delete_attr_function*)0)
-#define MPI_TYPE_DUP_FN ((MPI_Type_copy_attr_function*)MPI_DUP_FN)
typedef MPI_Comm_errhandler_function MPI_Comm_errhandler_fn;
#define MPI_INFO_ENV 1
XBT_PRIVATE int smpi_mpi_get_count(MPI_Status * status, MPI_Datatype datatype);
-XBT_PRIVATE int smpi_comm_keyval_create(MPI_Comm_copy_attr_function* copy_fn, MPI_Comm_delete_attr_function* delete_fn,
- int* keyval, void* extra_state);
-XBT_PRIVATE int smpi_comm_keyval_free(int* keyval);
-
-XBT_PRIVATE int smpi_type_attr_delete(MPI_Datatype type, int keyval);
-XBT_PRIVATE int smpi_type_attr_get(MPI_Datatype type, int keyval, void* attr_value, int* flag);
-XBT_PRIVATE int smpi_type_attr_put(MPI_Datatype type, int keyval, void* attr_value);
-XBT_PRIVATE int smpi_type_keyval_create(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn,
- int* keyval, void* extra_state);
-XBT_PRIVATE int smpi_type_keyval_free(int* keyval);
// utilities
extern XBT_PRIVATE double smpi_cpu_threshold;
extern XBT_PRIVATE double smpi_host_speed;
non_uniform_map_ = nullptr;
leaders_map_ = nullptr;
is_blocked_=0;
- attributes_=nullptr;
}
void Comm::destroy(Comm* comm)
(*newcomm) = new Comm(cp, this->topo());
int ret = MPI_SUCCESS;
- if(attributes_ !=nullptr){
- (*newcomm)->attributes_ = xbt_dict_new_homogeneous(nullptr);
- xbt_dict_cursor_t cursor = nullptr;
- char* key;
+ if(!attributes_.empty()){
int flag;
- void* value_in;
void* value_out;
- xbt_dict_foreach (attributes_, cursor, key, value_in) {
- smpi_key_elem elem = keyvals_.at(*key);
+ for(auto it = attributes_.begin(); it != attributes_.end(); it++){
+ smpi_key_elem elem = keyvals_.at((*it).first);
if (elem != nullptr && elem->copy_fn.comm_copy_fn != MPI_NULL_COPY_FN) {
- ret = elem->copy_fn.comm_copy_fn(this, *key, nullptr, value_in, &value_out, &flag);
+ ret = elem->copy_fn.comm_copy_fn(this, (*it).first, nullptr, (*it).second, &value_out, &flag);
if (ret != MPI_SUCCESS) {
Comm::destroy(*newcomm);
*newcomm = MPI_COMM_NULL;
- xbt_dict_cursor_free(&cursor);
return ret;
}
- if (flag)
- xbt_dict_set_ext((*newcomm)->attributes_, key, sizeof(int), value_out, nullptr);
+ if (flag){
+ elem->refcount++;
+ (*newcomm)->attributes_.insert({(*it).first, value_out});
+ }
}
}
}
}
void Comm::cleanup_attributes(){
- if(attributes_ !=nullptr){
- xbt_dict_cursor_t cursor = nullptr;
- char* key;
- void* value;
+ if(!attributes_.empty()){
int flag;
- xbt_dict_foreach (attributes_, cursor, key, value) {
+ for(auto it = attributes_.begin(); it != attributes_.end(); it++){
try{
- smpi_key_elem elem = keyvals_.at(*key);
+ smpi_key_elem elem = keyvals_.at((*it).first);
if (elem != nullptr && elem->delete_fn.comm_delete_fn != nullptr)
- elem->delete_fn.comm_delete_fn(this, *key, value, &flag);
+ elem->delete_fn.comm_delete_fn(this, (*it).first, (*it).second, &flag);
}catch(const std::out_of_range& oor) {
//already deleted, not a problem;
}
}
- xbt_dict_free(&attributes_);
}
}
smpi_process_set_replaying(true);
}
-int Comm::attr_delete(int keyval){
- smpi_key_elem elem = keyvals_.at(keyval);
- if(elem==nullptr)
- return MPI_ERR_ARG;
- if(elem->delete_fn.comm_delete_fn!=MPI_NULL_DELETE_FN){
- void* value = nullptr;
- int flag;
- if(this->attr_get(keyval, &value, &flag)==MPI_SUCCESS){
- int ret = elem->delete_fn.comm_delete_fn(this, keyval, value, &flag);
- if(ret!=MPI_SUCCESS)
- return ret;
- }
- }
- if(attributes_==nullptr)
- return MPI_ERR_ARG;
-
- xbt_dict_remove_ext(attributes_, reinterpret_cast<const char*>(&keyval), sizeof(int));
- return MPI_SUCCESS;
-}
-
-int Comm::attr_get(int keyval, void* attr_value, int* flag){
- smpi_key_elem elem = keyvals_.at(keyval);
- if(elem==nullptr)
- return MPI_ERR_ARG;
- if(attributes_==nullptr){
- *flag=0;
- return MPI_SUCCESS;
- }
- try {
- *static_cast<void**>(attr_value) =
- xbt_dict_get_ext(attributes_, reinterpret_cast<const char*>(&keyval), sizeof(int));
- *flag=1;
- }
- catch (xbt_ex& ex) {
- *flag=0;
- }
- return MPI_SUCCESS;
-}
-
-int Comm::attr_put(int keyval, void* attr_value){
- smpi_key_elem elem = keyvals_.at(keyval);
- if(elem==nullptr)
- return MPI_ERR_ARG;
- int flag;
- void* value = nullptr;
- this->attr_get(keyval, &value, &flag);
- if(flag!=0 && elem->delete_fn.comm_delete_fn!=MPI_NULL_DELETE_FN){
- int ret = elem->delete_fn.comm_delete_fn(this, keyval, value, &flag);
- if(ret!=MPI_SUCCESS)
- return ret;
- }
- if(attributes_==nullptr)
- attributes_ = xbt_dict_new_homogeneous(nullptr);
-
- xbt_dict_set_ext(attributes_, reinterpret_cast<const char*>(&keyval), sizeof(int), attr_value, nullptr);
- return MPI_SUCCESS;
-}
-
MPI_Comm Comm::f2c(int id) {
if(id == -2) {
return MPI_COMM_SELF;
int is_uniform_;
int* non_uniform_map_; //set if smp nodes have a different number of processes allocated
int is_blocked_;// are ranks allocated on the same smp node contiguous ?
- xbt_dict_t attributes_;
public:
static std::unordered_map<int, smpi_key_elem> keyvals_;
static void unref(MPI_Comm comm);
static void destroy(MPI_Comm comm);
void init_smp();
- int attr_delete(int keyval);
- int attr_get(int keyval, void* attr_value, int* flag);
- int attr_put(int keyval, void* attr_value);
int add_f();
static void free_f(int id);
std::unordered_map<int, smpi_key_elem> Datatype::keyvals_;
int Datatype::keyval_id_=0;
-Datatype::Datatype(int size,MPI_Aint lb, MPI_Aint ub, int flags) : name_(nullptr), size_(size), lb_(lb), ub_(ub), flags_(flags), attributes_(nullptr), refcount_(1){
+Datatype::Datatype(int size,MPI_Aint lb, MPI_Aint ub, int flags) : name_(nullptr), size_(size), lb_(lb), ub_(ub), flags_(flags), refcount_(1){
#if HAVE_MC
if(MC_is_active())
MC_ignore(&(refcount_), sizeof(refcount_));
}
//for predefined types, so in_use = 0.
-Datatype::Datatype(char* name, int size,MPI_Aint lb, MPI_Aint ub, int flags) : name_(name), size_(size), lb_(lb), ub_(ub), flags_(flags), attributes_(nullptr), refcount_(0){
+Datatype::Datatype(char* name, int size,MPI_Aint lb, MPI_Aint ub, int flags) : name_(name), size_(size), lb_(lb), ub_(ub), flags_(flags), refcount_(0){
#if HAVE_MC
if(MC_is_active())
MC_ignore(&(refcount_), sizeof(refcount_));
#endif
}
-Datatype::Datatype(Datatype *datatype, int* ret) : name_(nullptr), lb_(datatype->lb_), ub_(datatype->ub_), flags_(datatype->flags_), attributes_(nullptr), refcount_(1)
+Datatype::Datatype(Datatype *datatype, int* ret) : name_(nullptr), lb_(datatype->lb_), ub_(datatype->ub_), flags_(datatype->flags_), refcount_(1)
{
flags_ &= ~DT_FLAG_PREDEFINED;
*ret = MPI_SUCCESS;
if(datatype->name_)
name_ = xbt_strdup(datatype->name_);
- if(datatype->attributes_ !=nullptr){
- attributes_ = xbt_dict_new_homogeneous(nullptr);
- xbt_dict_cursor_t cursor = nullptr;
- char* key;
+ if(!(datatype->attributes_.empty())){
int flag;
- void* value_in;
void* value_out;
- xbt_dict_foreach (datatype->attributes_, cursor, key, value_in) {
- smpi_key_elem elem = keyvals_.at(atoi(key));
+ for(auto it = datatype->attributes_.begin(); it != datatype->attributes_.end(); it++){
+ smpi_key_elem elem = keyvals_.at((*it).first);
+
if (elem != nullptr && elem->copy_fn.type_copy_fn != MPI_NULL_COPY_FN) {
- *ret = elem->copy_fn.type_copy_fn(datatype, atoi(key), nullptr, value_in, &value_out, &flag);
+ *ret = elem->copy_fn.type_copy_fn(datatype, (*it).first, nullptr, (*it).second, &value_out, &flag);
if (*ret != MPI_SUCCESS) {
- xbt_dict_cursor_free(&cursor);
break;
}
- if (flag)
- xbt_dict_set_ext(attributes_, key, sizeof(int), value_out, nullptr);
+ if (flag){
+ elem->refcount++;
+ attributes_.insert({(*it).first, value_out});
+ }
}
}
}
return;
}
- if(attributes_ !=nullptr){
- xbt_dict_cursor_t cursor = nullptr;
- char* key;
- void * value;
+ if(!attributes_.empty()){
int flag;
- xbt_dict_foreach(attributes_, cursor, key, value){
+ for(auto it = attributes_.begin(); it != attributes_.end(); it++){
try{
- smpi_key_elem elem = keyvals_.at(atoi(key));
- if(elem!=nullptr && elem->delete_fn.type_delete_fn!=nullptr)
- elem->delete_fn.type_delete_fn(this,*key, value, &flag);
+ smpi_key_elem elem = keyvals_.at((*it).first);
+ if (elem != nullptr && elem->delete_fn.type_delete_fn != nullptr)
+ elem->delete_fn.type_delete_fn(this, (*it).first, (*it).second, &flag);
}catch(const std::out_of_range& oor) {
//already deleted, not a problem;
}
}
- xbt_dict_free(&attributes_);
}
xbt_free(name_);
name_ = xbt_strdup(name);
}
-int Datatype::attr_delete(int keyval){
- smpi_key_elem elem = keyvals_.at(keyval);
- if(elem==nullptr)
- return MPI_ERR_ARG;
- if(elem->delete_fn.type_delete_fn!=MPI_NULL_DELETE_FN){
- void * value = nullptr;
- int flag;
- if(this->attr_get(keyval, &value, &flag)==MPI_SUCCESS){
- int ret = elem->delete_fn.type_delete_fn(this, keyval, value, &flag);
- if(ret!=MPI_SUCCESS)
- return ret;
- }
- }
- if(attributes_==nullptr)
- return MPI_ERR_ARG;
-
- xbt_dict_remove_ext(attributes_, reinterpret_cast<const char*>(&keyval), sizeof(int));
- return MPI_SUCCESS;
-}
-
-
-int Datatype::attr_get(int keyval, void* attr_value, int* flag){
- smpi_key_elem elem = keyvals_.at(keyval);
- if(elem==nullptr)
- return MPI_ERR_ARG;
- if(attributes_==nullptr){
- *flag=0;
- return MPI_SUCCESS;
- }
- try {
- *static_cast<void**>(attr_value) = xbt_dict_get_ext(attributes_, reinterpret_cast<const char*>(&keyval), sizeof(int));
- *flag=1;
- }
- catch (xbt_ex& ex) {
- *flag=0;
- }
- return MPI_SUCCESS;
-}
-
-int Datatype::attr_put(int keyval, void* attr_value){
- smpi_key_elem elem = keyvals_.at(keyval);
- if(elem==nullptr)
- return MPI_ERR_ARG;
- int flag;
- void* value = nullptr;
- this->attr_get(keyval, &value, &flag);
- if(flag!=0 && elem->delete_fn.type_delete_fn!=MPI_NULL_DELETE_FN){
- int ret = elem->delete_fn.type_delete_fn(this, keyval, value, &flag);
- if(ret!=MPI_SUCCESS)
- return ret;
- }
- if(attributes_==nullptr)
- attributes_ = xbt_dict_new_homogeneous(nullptr);
-
- xbt_dict_set_ext(attributes_, reinterpret_cast<const char*>(&keyval), sizeof(int), attr_value, nullptr);
- return MPI_SUCCESS;
-}
-
int Datatype::pack(void* inbuf, int incount, void* outbuf, int outcount, int* position,MPI_Comm comm){
if (outcount - *position < incount*static_cast<int>(size_))
return MPI_ERR_BUFFER;
MPI_Aint lb_;
MPI_Aint ub_;
int flags_;
- xbt_dict_t attributes_;
int refcount_;
public:
int count);
virtual void unserialize( void* contiguous, void *noncontiguous,
int count, MPI_Op op);
- int attr_delete(int keyval);
- int attr_get(int keyval, void* attr_value, int* flag);
- int attr_put(int keyval, void* attr_value);
static int keyval_create(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state);
static int keyval_free(int* keyval);
int pack(void* inbuf, int incount, void* outbuf, int outcount, int* position, MPI_Comm comm);
--- /dev/null
+/* Copyright (c) 2007-2017. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "private.h"
+#include <unordered_map>
+#include <xbt/ex.hpp>
+
+namespace simgrid{
+namespace smpi{
+
+
+template <> int Keyval::call_deleter<Comm>(Comm* obj, smpi_key_elem elem, int keyval, void * value, int* flag){
+ if(elem->delete_fn.comm_delete_fn!=MPI_NULL_DELETE_FN){
+ int ret = elem->delete_fn.comm_delete_fn(obj, keyval, value, flag);
+ if(ret!=MPI_SUCCESS)
+ return ret;
+ }
+ return MPI_SUCCESS;
+}
+
+template <> int Keyval::call_deleter<Win>(Win* obj, smpi_key_elem elem, int keyval, void * value, int* flag){
+ if(elem->delete_fn.win_delete_fn!=MPI_NULL_DELETE_FN){
+ int ret = elem->delete_fn.win_delete_fn(obj, keyval, value, flag);
+ if(ret!=MPI_SUCCESS)
+ return ret;
+ }
+ return MPI_SUCCESS;
+}
+
+template <> int Keyval::call_deleter<Datatype>(Datatype* obj, smpi_key_elem elem, int keyval, void * value, int* flag){
+ if(elem->delete_fn.type_delete_fn!=MPI_NULL_DELETE_FN){
+ int ret = elem->delete_fn.type_delete_fn(obj, keyval, value, flag);
+ if(ret!=MPI_SUCCESS)
+ return ret;
+ }
+ return MPI_SUCCESS;
+}
+
+}
+}
--- /dev/null
+/* Copyright (c) 2010, 2013-2017. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef SMPI_KEYVALS_HPP_INCLUDED
+#define SMPI_KEYVALS_HPP_INCLUDED
+
+#include "private.h"
+#include <unordered_map>
+#include <xbt/ex.hpp>
+
+namespace simgrid{
+namespace smpi{
+
+
+typedef union smpi_delete_fn{
+ MPI_Comm_delete_attr_function *comm_delete_fn;
+ MPI_Type_delete_attr_function *type_delete_fn;
+ MPI_Win_delete_attr_function *win_delete_fn;
+} smpi_delete_fn;
+
+typedef union smpi_copy_fn{
+ MPI_Comm_copy_attr_function *comm_copy_fn;
+ MPI_Type_copy_attr_function *type_copy_fn;
+ MPI_Win_copy_attr_function *win_copy_fn;
+} smpi_copy_fn;
+
+typedef struct s_smpi_key_elem {
+ smpi_copy_fn copy_fn;
+ smpi_delete_fn delete_fn;
+ int refcount;
+} s_smpi_mpi_key_elem_t;
+typedef struct s_smpi_key_elem *smpi_key_elem;
+
+class Keyval{
+ protected:
+ std::unordered_map<int, void*> attributes_;
+ public:
+// Each subclass should have two members, as we want to separate the ones for Win, Comm, and Datatypes :
+// static std::unordered_map<int, smpi_key_elem> keyvals_;
+// static int keyval_id_;
+ template <typename T> static int keyval_create(smpi_copy_fn copy_fn, smpi_delete_fn delete_fn, int* keyval, void* extra_statee);
+ template <typename T> static int keyval_free(int* keyval);
+ template <typename T> int attr_delete(int keyval);
+ template <typename T> int attr_get(int keyval, void* attr_value, int* flag);
+ template <typename T> int attr_put(int keyval, void* attr_value);
+ template <typename T> static int call_deleter(T* obj, smpi_key_elem elem, int keyval, void * value, int* flag);
+};
+
+template <typename T> int Keyval::keyval_create(smpi_copy_fn copy_fn, smpi_delete_fn delete_fn, int* keyval, void* extra_state){
+
+ smpi_key_elem value = (smpi_key_elem) xbt_new0(s_smpi_mpi_key_elem_t,1);
+
+ value->copy_fn=copy_fn;
+ value->delete_fn=delete_fn;
+ value->refcount=1;
+
+ *keyval = T::keyval_id_;
+ T::keyvals_.insert({*keyval, value});
+ T::keyval_id_++;
+ return MPI_SUCCESS;
+}
+
+template <typename T> int Keyval::keyval_free(int* keyval){
+/* See MPI-1, 5.7.1. Freeing the keyval does not remove it if it
+ * is in use in an attribute */
+ smpi_key_elem elem = T::keyvals_.at(*keyval);
+ if(elem==0){
+ return MPI_ERR_ARG;
+ }
+ if(elem->refcount==1){
+ T::keyvals_.erase(*keyval);
+ xbt_free(elem);
+ }else{
+ elem->refcount--;
+ }
+ return MPI_SUCCESS;
+}
+
+//specialized in smpi_keyvals.cpp
+template <typename T> int Keyval::call_deleter(T* obj, smpi_key_elem elem, int keyval, void * value, int* flag){
+ return MPI_SUCCESS;
+}
+
+template <typename T> int Keyval::attr_delete(int keyval){
+ smpi_key_elem elem = T::keyvals_.at(keyval);
+ if(elem==nullptr)
+ return MPI_ERR_ARG;
+ elem->refcount--;
+ void * value = nullptr;
+ int flag;
+ if(this->attr_get<T>(keyval, &value, &flag)==MPI_SUCCESS){
+ int ret = call_deleter<T>((T*)this, elem, keyval,value,&flag);
+ if(ret!=MPI_SUCCESS)
+ return ret;
+ }
+ if(attributes_.empty())
+ return MPI_ERR_ARG;
+ attributes_.erase(keyval);
+ return MPI_SUCCESS;
+}
+
+
+template <typename T> int Keyval::attr_get(int keyval, void* attr_value, int* flag){
+ smpi_key_elem elem = T::keyvals_.at(keyval);
+ if(elem==nullptr)
+ return MPI_ERR_ARG;
+ if(attributes_.empty()){
+ *flag=0;
+ return MPI_SUCCESS;
+ }
+ try {
+ *static_cast<void**>(attr_value) = attributes_.at(keyval);
+ *flag=1;
+ }
+ catch (const std::out_of_range& oor) {
+ *flag=0;
+ }
+ return MPI_SUCCESS;
+}
+
+template <typename T> int Keyval::attr_put(int keyval, void* attr_value){
+ smpi_key_elem elem = T::keyvals_.at(keyval);
+ if(elem==nullptr)
+ return MPI_ERR_ARG;
+ elem->refcount++;
+ void * value = nullptr;
+ int flag;
+ this->attr_get<T>(keyval, &value, &flag);
+ if(flag!=0){
+ int ret = call_deleter<T>((T*)this, elem, keyval,value,&flag);
+ if(ret!=MPI_SUCCESS)
+ return ret;
+ }
+ attributes_.insert({keyval, attr_value});
+ return MPI_SUCCESS;
+}
+
+}
+}
+
+#endif
else if (comm==MPI_COMM_NULL)
return MPI_ERR_COMM;
else
- return comm->attr_delete(keyval);
+ return comm->attr_delete<Comm>(keyval);
}
int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) {
*static_cast<int**>(attr_value) = &one;
return MPI_SUCCESS;
default:
- return comm->attr_get(keyval, attr_value, flag);
+ return comm->attr_get<Comm>(keyval, attr_value, flag);
}
}
else if (comm==MPI_COMM_NULL)
return MPI_ERR_COMM;
else
- return comm->attr_put(keyval, attr_value);
+ return comm->attr_put<Comm>(keyval, attr_value);
}
int PMPI_Comm_get_attr (MPI_Comm comm, int comm_keyval, void *attribute_val, int *flag)
if (type==MPI_DATATYPE_NULL)
return MPI_ERR_TYPE;
else
- return type->attr_get(type_keyval, attribute_val, flag);
+ return type->attr_get<Datatype>(type_keyval, attribute_val, flag);
}
int PMPI_Type_set_attr (MPI_Datatype type, int type_keyval, void *attribute_val)
if (type==MPI_DATATYPE_NULL)
return MPI_ERR_TYPE;
else
- return type->attr_put(type_keyval, attribute_val);
+ return type->attr_put<Datatype>(type_keyval, attribute_val);
}
int PMPI_Type_delete_attr (MPI_Datatype type, int type_keyval)
if (type==MPI_DATATYPE_NULL)
return MPI_ERR_TYPE;
else
- return type->attr_delete(type_keyval);
+ return type->attr_delete<Datatype>(type_keyval);
}
int PMPI_Type_create_keyval(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval,
src/smpi/smpi_datatype.hpp
src/smpi/smpi_info.cpp
src/smpi/smpi_info.hpp
+ src/smpi/smpi_keyvals.cpp
src/smpi/smpi_keyvals.hpp
src/smpi/smpi_datatype_derived.cpp
src/smpi/smpi_datatype_derived.hpp