Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use a std::unique_ptr, and avoid explicit new/delete.
[simgrid.git] / src / smpi / include / smpi_keyvals.hpp
index 46144a9..b594f09 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2021. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2010-2022. 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,6 +34,8 @@ 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{
@@ -50,7 +53,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 +64,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 +88,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;
@@ -105,6 +111,8 @@ template <typename T> int Keyval::attr_delete(int keyval){
     return ret;
 
   elem.refcount--;
+  if (elem.deleted && elem.refcount == 0)
+    T::keyvals_.erase(elem_it);
   attributes().erase(attr);
   return MPI_SUCCESS;
 }
@@ -112,7 +120,7 @@ template <typename T> int Keyval::attr_delete(int keyval){
 
 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 (elem_it == T::keyvals_.end() || elem_it->second.deleted)
     return MPI_ERR_ARG;
 
   auto attr = attributes().find(keyval);
@@ -127,7 +135,7 @@ 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;
@@ -146,17 +154,17 @@ 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;
-    }
+    xbt_assert(elem_it != T::keyvals_.end());
+    smpi_key_elem& elem = elem_it->second;
+    int flag            = 0;
+    call_deleter<T>((T*)this, elem, it.first, it.second, &flag);
+    elem.refcount--;
+    if (elem.deleted && elem.refcount == 0)
+      T::keyvals_.erase(elem_it);
   }
+  attributes().clear();
 }
 
 }