Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / inference_engine / cpp_interfaces / ie_task_synchronizer.hpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #pragma once
6
7 #include <vector>
8 #include <memory>
9 #include <mutex>
10 #include <condition_variable>
11 #include <thread>
12 #include <queue>
13 #include "details/ie_exception.hpp"
14
15 namespace InferenceEngine {
16
17 #define MAX_NUMBER_OF_TASKS_IN_QUEUE 10
18
19 class TaskSynchronizer {
20 public:
21     typedef std::shared_ptr<TaskSynchronizer> Ptr;
22
23     TaskSynchronizer() : _taskCount(0) {}
24
25     virtual void lock() {
26         auto taskID = _addTaskToQueue();
27         _waitInQueue(taskID);
28     }
29
30     virtual void unlock() {
31         std::unique_lock<std::mutex> lockTask(_taskMutex);
32         if (!_taskQueue.empty()) {
33             {
34                 std::lock_guard<std::mutex> lock(_queueMutex);
35                 _taskQueue.pop();
36             }
37             _taskCondVar.notify_all();
38         }
39     }
40
41     size_t queueSize() const {
42         return _taskQueue.size();
43     }
44
45 private:
46     unsigned int _taskCount;
47     std::queue<unsigned int> _taskQueue;
48     std::mutex _queueMutex;
49     std::mutex _taskMutex;
50     std::condition_variable _taskCondVar;
51
52 protected:
53     virtual unsigned int _getTaskID() {
54         return _taskCount++;
55     }
56
57     virtual unsigned int _addTaskToQueue() {
58         std::lock_guard<std::mutex> lock(_queueMutex);
59         auto taskID = _getTaskID();
60         if (!_taskQueue.empty() && _taskQueue.size() >= MAX_NUMBER_OF_TASKS_IN_QUEUE) {
61             THROW_IE_EXCEPTION << "Failed to add more than " << MAX_NUMBER_OF_TASKS_IN_QUEUE << " tasks to queue";
62         }
63         _taskQueue.push(taskID);
64         return taskID;
65     }
66
67     virtual void _waitInQueue(unsigned int taskID) {
68         std::unique_lock<std::mutex> lock(_taskMutex);
69         _taskCondVar.wait(lock, [&]() { return taskID == _taskQueue.front(); });
70     }
71 };
72
73 class ScopedSynchronizer {
74 public:
75     explicit ScopedSynchronizer(TaskSynchronizer::Ptr &taskSynchronizer) : _taskSynchronizer(
76             taskSynchronizer) {
77         _taskSynchronizer->lock();
78     }
79
80     ~ScopedSynchronizer() {
81         _taskSynchronizer->unlock();
82     }
83
84 private:
85     TaskSynchronizer::Ptr &_taskSynchronizer;
86 };
87
88 }  // namespace InferenceEngine