Repository: opencv/opencv
File: modules/gapi/include/opencv2/gapi/infer/ov.hpp (C++)

Code before:
    detail::ParamDesc m_desc;
};

} // namespace ov

namespace wip { namespace ov {
/**
 * @brief Ask G-API OpenVINO backend to run only inference of model provided.
 *
 * G-API OpenVINO backend will perform only the inference of the model provided
 * without populating input and copying back output data.
 * This mode is used to evaluate the pure inference performance of the model without
 * taking into account the i/o data transfer.
 */
struct benchmark_mode { };

struct workload_type {
    using callback = std::function<void(const std::string &type)>;
    using listener = std::pair<int, callback>;
    std::shared_ptr<void> addListener(callback cb){
        int id = nextId++;
        listeners.emplace_back(id, std::move(cb));

        auto remover = [this, id](void*){ removeListener(id);};

        return std::shared_ptr<void>(nullptr, remover);
    }
    void setWorkloadType(const std::string &type) {
        for(const listener& l : listeners) {
            l.second(type);
        }
    }
 private:
    std::vector<listener> listeners;
    int nextId = 0;
    void removeListener(int id) {
        listeners.erase(std::remove_if(listeners.begin(), listeners.end(), [=](listener& pair){return pair.first == id;}), listeners.end());
    }
};
} // namespace ov
} // namespace wip

} // namespace gapi

namespace detail
{
    template<> struct CompileArgTag<cv::gapi::wip::ov::benchmark_mode>
    {
        static const char* tag() { return "gapi.wip.ov.benchmark_mode"; }
    };
    template<> struct CompileArgTag<cv::gapi::wip::ov::workload_type>

Review comment (suggestion):
I don't think it is a good idea to remove listeners that way. It seems a bit tricky. I understand that this variable may outlive G-API OV backend. But, might be, we can clean this variable's listeners in the destructor of G-API OV backend itself. Please note that we are the "users" of given API to add listeners and we 100% know when we add a listener and when we can remove it, so there is no need for some RAII idiom for remove. If this is allowable, we can preserve these compile args somewhere in backend to access variable in the destructor.

Code after:
    std::string m_tag;
    detail::ParamDesc m_desc;
};

} // namespace ov

namespace wip { namespace ov {
/**
 * @brief Ask G-API OpenVINO backend to run only inference of model provided.
 *
 * G-API OpenVINO backend will perform only the inference of the model provided
 * without populating input and copying back output data.
 * This mode is used to evaluate the pure inference performance of the model without
 * taking into account the i/o data transfer.
 */
struct benchmark_mode { };

class WorkloadTypeOV : public WorkloadType {};
using WorkloadTypeOVPtr = std::shared_ptr<cv::gapi::wip::ov::WorkloadTypeOV>;

} // namespace ov
} // namespace wip

} // namespace gapi

namespace detail
{
    template<> struct CompileArgTag<cv::gapi::wip::ov::benchmark_mode>
    {
        static const char* tag() { return "gapi.wip.ov.benchmark_mode"; }
    };
    template<> struct CompileArgTag<cv::gapi::wip::ov::WorkloadTypeOVPtr>
    {
        static const char* tag() { return "gapi.wip.ov.workload_type"; }
    };
}

} // namespace cv

#endif // OPENCV_GAPI_INFER_OV_HPP