Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / inference_engine / cpp_interfaces / ie_task.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <vector>
6 #include <mutex>
7 #include <memory>
8 #include <condition_variable>
9 #include <thread>
10 #include <queue>
11 #include <ie_profiling.hpp>
12 #include "details/ie_exception.hpp"
13 #include "exception2status.hpp"
14 #include "ie_task_synchronizer.hpp"
15 #include "ie_task.hpp"
16 #include "ie_task_executor.hpp"
17
18 namespace InferenceEngine {
19
20 Task::Task() : _status(TS_INITIAL) {
21     _function = [&]() {
22         _status = TS_DONE;
23         return;
24     };
25 }
26
27 Task::Task(std::function<void()> function) : _status(TS_INITIAL), _function(function) {
28     if (!function) THROW_IE_EXCEPTION << "Failed to create Task object with null function";
29 }
30
31 Task::Status Task::runNoThrowNoBusyCheck() noexcept {
32     IE_PROFILING_AUTO_SCOPE(TaskExecution);
33     try {
34         _exceptionPtr = nullptr;
35         _function();
36         setStatus(TS_DONE);
37     } catch (...) {
38         _exceptionPtr = std::current_exception();
39         setStatus(TS_ERROR);
40     }
41     _isTaskDoneCondVar.notify_all();
42     return getStatus();
43 }
44
45 Task::Status Task::runWithSynchronizer(TaskSynchronizer::Ptr &taskSynchronizer) {
46     if (occupy()) {
47         ScopedSynchronizer scopedSynchronizer(taskSynchronizer);
48         runNoThrowNoBusyCheck();
49     }
50     return getStatus();
51 }
52
53 Task::Status Task::wait(int64_t millis_timeout) {
54     _isOnWait = true;
55     std::exception_ptr exceptionPtr;
56     try {
57         std::unique_lock<std::mutex> lock(_taskStatusMutex);
58         if (_status != TS_INITIAL) {
59             auto predicate = [&]() -> bool { return _status == TS_DONE || _status == TS_ERROR; };
60             if (millis_timeout < 0) {
61                 _isTaskDoneCondVar.wait(lock, predicate);
62             } else {
63                 _isTaskDoneCondVar.wait_for(lock, std::chrono::milliseconds(millis_timeout), predicate);
64             }
65         }
66     } catch (...) {
67         exceptionPtr = std::current_exception();
68     }
69     if (exceptionPtr) std::rethrow_exception(exceptionPtr);
70     _isOnWait = false;
71     return _status;
72 }
73
74 bool Task::occupy() {
75     std::unique_lock<std::mutex> guard(_taskStatusMutex);
76     if (_status == Task::TS_BUSY) return false;
77     _status = TS_BUSY;
78     return true;
79 }
80
81 Task::Status Task::getStatus() {
82     std::unique_lock<std::mutex> guard(_taskStatusMutex);
83     return _status;
84 }
85
86 void Task::checkException() {
87     if (_exceptionPtr) {
88         std::rethrow_exception(_exceptionPtr);
89     }
90 }
91
92 StatusCode Task::TaskStatus2StatusCode(Task::Status status) {
93     switch (status) {
94         case Status::TS_DONE:
95             return OK;
96         case Status::TS_ERROR:
97             return GENERAL_ERROR;
98         case Status::TS_BUSY:
99         case Status::TS_POSTPONED:
100             return RESULT_NOT_READY;
101         case Status::TS_INITIAL:
102             return INFER_NOT_STARTED;
103         default:
104             THROW_IE_EXCEPTION << "Logic error: unknown state of InferRequest!";
105     }
106 }
107
108 void Task::setStatus(Task::Status status) {
109     std::unique_lock<std::mutex> guard(_taskStatusMutex);
110     _status = status;
111 }
112
113 bool Task::isOnWait() {
114     return _isOnWait;
115 }
116
117 }  // namespace InferenceEngine