clean up with copy-constructor 36/311736/5
authorInki Dae <inki.dae@samsung.com>
Mon, 27 May 2024 02:39:43 +0000 (11:39 +0900)
committerInki Dae <inki.dae@samsung.com>
Tue, 28 May 2024 04:17:53 +0000 (13:17 +0900)
Clean up with copy-constructor. With this patch,
Manual copy to ImageDataType can be dropped.

Change-Id: I1669ac0fe1706561b903bd59933a9f217f560fce
Signed-off-by: Inki Dae <inki.dae@samsung.com>
common/include/SingleoCommonTypes.h
services/auto_zoom/src/AutoZoom.cpp
services/task_manager/src/InferenceNode.cpp
services/task_manager/src/TaskManager.cpp
test/services/test_task_manager.cpp

index 03b0cd5d9b67c2ff8031a0db97a86bc632715b9d..31cabf34639cada78552543f500e79948e796b94 100644 (file)
 #ifndef __SINGLEO_COMMON_TYPES_H__
 #define __SINGLEO_COMMON_TYPES_H__
 
+#include <cstring>
 #include <vector>
+#include "SingleoLog.h"
+#include "SingleoException.h"
 
 namespace singleo
 {
@@ -54,14 +57,34 @@ struct FileDataType : public BaseDataType {
 };
 
 struct ImageDataType : public BaseDataType {
-       ImageDataType() : BaseDataType(DataType::IMAGE)
-       {}
        unsigned char *ptr {};
        unsigned int width {};
        unsigned int height {};
        unsigned int byte_per_pixel {};
        ImagePixelFormat pixel_format { ImagePixelFormat::NONE };
        bool custom { false };
+
+       ImageDataType() : BaseDataType(DataType::IMAGE)
+       {}
+
+       ImageDataType(const ImageDataType &other) : BaseDataType(DataType::IMAGE)
+       {
+               unsigned int size = other.width * other.height * other.byte_per_pixel;
+               if (size == 0) {
+                       SINGLEO_LOGE("ImageDataType::operator=() : Invalid size");
+                       throw singleo::exception::InvalidOperation("ImageDataType::operator=() : Invalid size");
+               }
+
+               ptr = new unsigned char[size];
+               memcpy(ptr, other.ptr, size);
+
+               width = other.width;
+               height = other.height;
+               byte_per_pixel = other.byte_per_pixel;
+               pixel_format = other.pixel_format;
+       }
+
+       ImageDataType &operator=(const ImageDataType &other) = delete;
 };
 
 struct RawDataType : public BaseDataType {
index 72341a8d0e64082df632f19f4321a2c5d5588b87..34c8c6cffc03399b0e982f9781d9131cc365f661 100644 (file)
@@ -91,13 +91,7 @@ void AutoZoom::inputFeedCb(BaseDataType &data)
 {
        ImagePreprocessor preprocessor(data);
        ImageDataType preprocessed = dynamic_cast<ImageDataType &>(preprocessor.getData());
-       ImageDataType copied = preprocessed;
-       size_t buffer_size = copied.width * copied.height * copied.byte_per_pixel;
-
-       // We have to avoid from grapping input feed stream so copy the captured data to new one.
-       // Ps. This allocated buffer should be released as soon as the completion of invoke in async manager's thread loop.
-       copied.ptr = new unsigned char[buffer_size];
-       memcpy(copied.ptr, preprocessed.ptr, buffer_size);
+       ImageDataType copied(preprocessed);
 
        if (_user_cb) {
                // if postprocessor isn't in progress, postprocess current camera preview image.
@@ -111,6 +105,7 @@ void AutoZoom::inputFeedCb(BaseDataType &data)
        }
 
        // Make sure to release copied buffer if incoming queue isn't empty so skipped pushing the buffer.
+       // If empty then push the buffer to the incoming queue. This buffer will be released at the end of runTaskManager function.
        if (_async_manager->pushInput(copied) != SINGLEO_ERROR_NONE)
                delete copied.ptr;
 }
@@ -190,11 +185,10 @@ void AutoZoom::performAsync()
 
                auto_zoom->runTaskManager(data);
 
-               // This buffer was allocated and copied in inputServiceCb callback.
-               // So make sure to release this buffer here.
-               auto specific_data = dynamic_cast<ImageDataType &>(data);
+               auto imageData = dynamic_cast<ImageDataType &>(data);
 
-               delete specific_data.ptr;
+               // A given imageData has been used so release it here.
+               delete imageData.ptr;
        });
 }
 
index ed158adca63b2a554a6b5aec73a11cc286822b9f..97f2d3f0f7481a95d4e0df7e6b6a3257812e9c67 100644 (file)
@@ -48,6 +48,15 @@ void InferenceNode::invoke()
 {
        // TODO. consider for multiple inputs later.
        _task->invoke(*_inputs[0]);
+
+       auto input = dynamic_pointer_cast<ImageDataType>(_inputs[0]);
+
+       // Inference request has been completed so release input data if the data was internally allocated
+       // by callback node.
+       if (input->custom)
+               delete input->ptr;
+
+       _inputs.clear();
 }
 
 BaseResultType &InferenceNode::getTaskResult()
index 874f680b669959d39d3fdcfdb22026a842327a69..534e21b2660b5364d235e46f54a3b9f75567f17e 100644 (file)
@@ -61,15 +61,6 @@ void TaskManager::threadCb(shared_ptr<INode> &node)
                }
 
                node->invoke();
-
-               auto input = dynamic_pointer_cast<ImageDataType>(node->getInputs()[0]);
-
-               // Inference request has been completed so release input data if the data was internally allocated by callback node.
-               if (input->custom)
-                       delete input->ptr;
-
-               // Service request to 'input' has been completed so clean up it.
-               node->getInputs().clear();
                node->wakeup();
 
                return;
@@ -146,8 +137,10 @@ void TaskManager::verifyGraph()
                                degreeMap[d_node]++;
 
                                if (d_node->getType() != NodeType::INFERENCE && d_node->getType() != NodeType::TRAINING) {
-                                       SINGLEO_LOGE("The bridge node should be located between two task nodes such as InferenceNode or TrainingNode.");
-                                       throw InvalidOperation("The bridge node should be located between two task nodes such as InferenceNode or TrainingNode.");
+                                       SINGLEO_LOGE(
+                                                       "The bridge node should be located between two task nodes such as InferenceNode or TrainingNode.");
+                                       throw InvalidOperation(
+                                                       "The bridge node should be located between two task nodes such as InferenceNode or TrainingNode.");
                                }
                        }
                } else if (node->getType() == NodeType::INFERENCE || node->getType() == NodeType::TRAINING) {
index 53b972520d38b8dca81daf75fde6c1252c54aeb1..3418fa0b3c996588860f70cc08913f7dd8c19dd9 100644 (file)
@@ -39,13 +39,9 @@ void BridgeNodeCallback(INode *node)
 {
        auto callbackNode = dynamic_cast<CallbackNode *>(node);
        shared_ptr<ImageDataType> imageData = dynamic_pointer_cast<ImageDataType>(callbackNode->getInputs()[0]);
-       size_t buffer_size = imageData->width * imageData->height * imageData->byte_per_pixel;
-       ImageDataType newImage;
+       ImageDataType newImage(*imageData);
        const int answer[][4] = { { 553, 87, 583, 129 }, { 397, 110, 427, 149 } };
 
-       newImage = *imageData;
-       newImage.ptr = new unsigned char[buffer_size];
-       memcpy(newImage.ptr, imageData->ptr, buffer_size);
        newImage.custom = true;
 
        cv::Mat cv_image(cv::Size(newImage.width, newImage.height), CV_MAKETYPE(CV_8U, 3), newImage.ptr);