Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / src / smpi / include / smpi_keyvals.hpp
index ab07655..768bc51 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2021. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2010-2023. 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. */
@@ -7,6 +7,7 @@
 #define SMPI_KEYVALS_HPP_INCLUDED
 
 #include "smpi/smpi.h"
+#include "xbt/asserts.h"
 
 #include <unordered_map>
 
@@ -33,10 +34,11 @@ struct smpi_key_elem {
   smpi_delete_fn delete_fn;
   void* extra_state;
   int refcount;
+  bool deleted;
+  bool delete_attr; // if true, xbt_free(attr) on delete: used by Fortran bindings
 };
 
-namespace simgrid{
-namespace smpi{
+namespace simgrid::smpi {
 
 class Keyval{
   private:
@@ -50,7 +52,7 @@ class Keyval{
 //    static int keyval_id_;
     template <typename T>
     static int keyval_create(const smpi_copy_fn& copy_fn, const smpi_delete_fn& delete_fn, int* keyval,
-                             void* extra_state);
+                             void* extra_state, bool delete_attr = false);
     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);
@@ -61,13 +63,16 @@ class Keyval{
 };
 
 template <typename T>
-int Keyval::keyval_create(const smpi_copy_fn& copy_fn, const smpi_delete_fn& delete_fn, int* keyval, void* extra_state)
+int Keyval::keyval_create(const smpi_copy_fn& copy_fn, const smpi_delete_fn& delete_fn, int* keyval, void* extra_state,
+                          bool delete_attr)
 {
   smpi_key_elem value;
   value.copy_fn     = copy_fn;
   value.delete_fn   = delete_fn;
   value.extra_state = extra_state;
-  value.refcount    = 1;
+  value.refcount    = 0;
+  value.deleted     = false;
+  value.delete_attr = delete_attr;
 
   *keyval = T::keyval_id_;
   T::keyvals_.emplace(*keyval, std::move(value));
@@ -82,7 +87,7 @@ template <typename T> int Keyval::keyval_free(int* keyval){
     return MPI_ERR_ARG;
 
   smpi_key_elem& elem = elem_it->second;
-  elem.refcount--;
+  elem.deleted        = true;
   if (elem.refcount == 0)
     T::keyvals_.erase(elem_it);
   *keyval = MPI_KEYVAL_INVALID;
@@ -94,29 +99,28 @@ template <typename T> int Keyval::attr_delete(int keyval){
   if (elem_it == T::keyvals_.end())
     return MPI_ERR_ARG;
 
+  auto attr = attributes().find(keyval);
+  if (attr == attributes().end())
+    return MPI_ERR_ARG;
+
   smpi_key_elem& elem = elem_it->second;
+  int flag            = 0;
+  if (int ret = call_deleter<T>((T*)this, elem, keyval, attr->second, &flag); ret != MPI_SUCCESS)
+    return ret;
+
   elem.refcount--;
-  void * value = nullptr;
-  int flag=0;
-  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);
+  if (elem.deleted && elem.refcount == 0)
+    T::keyvals_.erase(elem_it);
+  attributes().erase(attr);
   return MPI_SUCCESS;
 }
 
 
 template <typename T> int Keyval::attr_get(int keyval, void* attr_value, int* flag){
-  auto elem_it = T::keyvals_.find(keyval);
-  if (elem_it == T::keyvals_.end())
+  if (auto elem_it = T::keyvals_.find(keyval); elem_it == T::keyvals_.end() || elem_it->second.deleted)
     return MPI_ERR_ARG;
 
-  auto attr = attributes().find(keyval);
-  if (attr != attributes().end()) {
+  if (auto attr = attributes().find(keyval); attr != attributes().end()) {
     *static_cast<void**>(attr_value) = attr->second;
     *flag=1;
   } else {
@@ -127,18 +131,17 @@ template <typename T> int Keyval::attr_get(int keyval, void* attr_value, int* fl
 
 template <typename T> int Keyval::attr_put(int keyval, void* attr_value){
   auto elem_it = T::keyvals_.find(keyval);
-  if (elem_it == T::keyvals_.end())
+  if (elem_it == T::keyvals_.end() || elem_it->second.deleted)
     return MPI_ERR_ARG;
 
   smpi_key_elem& elem = elem_it->second;
-  int flag=0;
-  auto p  = attributes().emplace(keyval, attr_value);
-  if (p.second) {
+  if (auto [attr, inserted] = attributes().try_emplace(keyval, attr_value); inserted) {
     elem.refcount++;
   } else {
-    int ret = call_deleter<T>((T*)this, elem, keyval,p.first->second,&flag);
+    int flag = 0;
+    int ret  = call_deleter<T>((T*)this, elem, keyval, attr->second, &flag);
     // overwrite previous value
-    p.first->second = attr_value;
+    attr->second = attr_value;
     if(ret!=MPI_SUCCESS)
       return ret;
   }
@@ -146,20 +149,19 @@ template <typename T> int Keyval::attr_put(int keyval, void* attr_value){
 }
 
 template <typename T> void Keyval::cleanup_attr(){
-  int flag = 0;
-  for (auto const& it : attributes()) {
-    auto elem_it = T::keyvals_.find(it.first);
-    if (elem_it != T::keyvals_.end()) {
-      smpi_key_elem& elem = elem_it->second;
-      call_deleter<T>((T*)this, elem, it.first, it.second, &flag);
-    } else {
-      // already deleted, not a problem
-      flag = 0;
-    }
+  for (auto const& [key, value] : attributes()) {
+    auto elem_it = T::keyvals_.find(key);
+    xbt_assert(elem_it != T::keyvals_.end());
+    smpi_key_elem& elem = elem_it->second;
+    int flag            = 0;
+    call_deleter<T>((T*)this, elem, key, value, &flag);
+    elem.refcount--;
+    if (elem.deleted && elem.refcount == 0)
+      T::keyvals_.erase(elem_it);
   }
+  attributes().clear();
 }
 
-}
-}
+} // namespace simgrid::smpi
 
 #endif