[ext] Remove class static variables without locking
authorParichay Kapoor <pk.kapoor@samsung.com>
Thu, 16 Jan 2020 06:00:45 +0000 (15:00 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Fri, 14 Feb 2020 06:09:48 +0000 (22:09 -0800)
As extensions are supposed to be thread-safe, using class static variables without locks is not stable.
Move class static variables to class private local object variables for python, tensorflow and caffe2.
Also update corresponding usages.

Signed-off-by: Parichay Kapoor <pk.kapoor@samsung.com>
ext/nnstreamer/tensor_filter/tensor_filter_caffe2.cc
ext/nnstreamer/tensor_filter/tensor_filter_python.cc
ext/nnstreamer/tensor_filter/tensor_filter_tensorflow.cc

index ba231bf..868ecb4 100644 (file)
@@ -72,7 +72,7 @@ private:
 
   Workspace workSpace;
   NetDef initNet, predictNet;
-  static std::map <char*, Tensor*> inputTensorMap;
+  std::map <char*, Tensor*> inputTensorMap;
 
   int initInputTensor ();
 };
@@ -80,8 +80,6 @@ private:
 void init_filter_caffe2 (void) __attribute__ ((constructor));
 void fini_filter_caffe2 (void) __attribute__ ((destructor));
 
-std::map <char*, Tensor*> Caffe2Core::inputTensorMap;
-
 /**
  * @brief      Caffe2Core creator
  * @param      _model_path     : the logical path to '{model_name}.tffile' file
index af55d67..d7dde57 100644 (file)
@@ -100,6 +100,7 @@ public:
   int run (const GstTensorMemory * input, GstTensorMemory * output);
 
   int parseOutputTensors(PyObject* result, GstTensorsInfo * info);
+  void freeOutputTensors(void *data);
 
   /** @brief Return callback type */
   cb_type getCbType () { return callback_type; }
@@ -116,13 +117,13 @@ public:
   tensor_type getTensorType (NPY_TYPES npyType);
   NPY_TYPES getNumpyType (tensor_type tType);
 
-  static std::map <void*, PyArrayObject*> outputArrayMap;
 private:
 
   const std::string script_path;  /**< from model_path property */
   const std::string module_args;  /**< from custom property */
 
   std::string module_name;
+  std::map <void*, PyArrayObject*> outputArrayMap;
 
   cb_type callback_type;
 
@@ -140,8 +141,6 @@ private:
 void init_filter_py (void) __attribute__ ((constructor));
 void fini_filter_py (void) __attribute__ ((destructor));
 
-std::map <void*, PyArrayObject*> PYCore::outputArrayMap;
-
 /**
  * @brief      PYCore creator
  * @param      _script_path    : the logical path to '{script_name}.py' file
@@ -565,6 +564,24 @@ PYCore::parseOutputTensors(PyObject* result, GstTensorsInfo * info)
 }
 
 /**
+ * @brief free output tensor corresponding to the given data
+ * @param[data] The data element
+ */
+void
+PYCore::freeOutputTensors (void *data)
+{
+  std::map <void*, PyArrayObject*>::iterator it;
+
+  it = outputArrayMap.find(data);
+  if (it != outputArrayMap.end()){
+    Py_XDECREF(it->second);
+    outputArrayMap.erase (it);
+  } else {
+    g_critical("Cannot find output data: 0x%lx", (unsigned long) data);
+  }
+}
+
+/**
  * @brief      run the script with the input.
  * @param[in] input : The array of input tensors
  * @param[out]  output : The array of output tensors
@@ -740,13 +757,10 @@ py_run (const GstTensorFilterProperties * prop, void **private_data,
 static void
 py_destroyNotify (void **private_data, void *data)
 {
-  std::map <void*, PyArrayObject*>::iterator it;
-  it = PYCore::outputArrayMap.find(data);
-  if (it != PYCore::outputArrayMap.end()){
-    Py_XDECREF(it->second);
-    PYCore::outputArrayMap.erase (it);
-  } else {
-    g_critical("Cannot find output data: 0x%lx", (unsigned long) data);
+  PYCore *core = static_cast<PYCore *>(*private_data);
+
+  if (core) {
+    core->freeOutputTensors (data);
   }
 }
 
index cd5e9cf..840d04b 100644 (file)
@@ -74,8 +74,7 @@ public:
   int getInputTensorDim (GstTensorsInfo * info);
   int getOutputTensorDim (GstTensorsInfo * info);
   int run (const GstTensorMemory * input, GstTensorMemory * output);
-
-  static std::map < void *, TF_Tensor * >outputTensorMap;
+  void freeOutputTensor (void *data);
 
 private:
 
@@ -85,6 +84,7 @@ private:
   GstTensorsInfo outputTensorMeta;  /**< The tensor info of output tensors from user input */
 
   std::vector < tf_tensor_info_s > input_tensor_info; /* hold information for TF */
+  std::map < void *, TF_Tensor * > outputTensorMap;
 
   TF_Graph *graph;
   TF_Session *session;
@@ -97,8 +97,6 @@ private:
 void init_filter_tf (void) __attribute__ ((constructor));
 void fini_filter_tf (void) __attribute__ ((destructor));
 
-std::map <void*, TF_Tensor*> TFCore::outputTensorMap;
-
 /**
  * @brief      TFCore creator
  * @param      _model_path     : the logical path to '{model_name}.pb' file
@@ -590,6 +588,18 @@ failed:
 }
 
 /**
+ * @brief free output tensor corresponding to the given data
+ * @param[in] data The data element
+ */
+void
+TFCore::freeOutputTensor (void *data)
+{
+  TF_Tensor *output_tensor = outputTensorMap.find (data)->second;
+  TF_DeleteTensor (output_tensor);
+  outputTensorMap.erase (data);
+}
+
+/**
  * @brief Free privateData and move on.
  */
 static void
@@ -720,8 +730,11 @@ tf_getOutputDim (const GstTensorFilterProperties * prop, void **private_data,
 static void
 tf_destroyNotify (void **private_data, void *data)
 {
-  TF_DeleteTensor ( (TFCore::outputTensorMap.find (data))->second);
-  TFCore::outputTensorMap.erase (data);
+  TFCore *core = static_cast<TFCore *>(*private_data);
+
+  if (core) {
+    core->freeOutputTensor (data);
+  }
 }
 
 static gchar filter_subplugin_tensorflow[] = "tensorflow";