blob: efaacb3dcb83674354e092d2c1bf32817963cefc [file] [log] [blame]
Michael Butler0e2ac1b2017-09-01 10:59:38 -07001#include "Event.h"
2#include <android-base/logging.h>
3
4namespace android {
5namespace hardware {
6namespace neuralnetworks {
7namespace V1_0 {
8namespace implementation {
9
10Event::Event() : mStatus(Status::WAITING) {}
11
12Event::~Event() {
David Gross0380d7f2017-09-11 16:23:17 -070013 // Note that we cannot call Event::join_thread from here: Event is
14 // intended to be reference counted, and it is possible that the
15 // reference count drops to zero in the bound thread, causing the
16 // bound thread to call this destructor. If a thread tries to join
17 // itself, it throws an exception, producing a message like the
18 // following:
19 //
20 // terminating with uncaught exception of type std::__1::system_error:
21 // thread::join failed: Resource deadlock would occur
Michael Butler0e2ac1b2017-09-01 10:59:38 -070022}
23
Michael Butler61ae6ed2017-09-11 20:27:50 -070024Return<void> Event::notify(ErrorStatus status) {
Michael Butler0e2ac1b2017-09-01 10:59:38 -070025 {
26 std::lock_guard<std::mutex> lock(mMutex);
Michael Butler61ae6ed2017-09-11 20:27:50 -070027 mStatus = status == ErrorStatus::NONE ? Status::SUCCESS : Status::ERROR;
Michael Butler0e2ac1b2017-09-01 10:59:38 -070028 if (mStatus == Status::SUCCESS && mCallback != nullptr) {
29 bool success = mCallback();
30 if (!success) {
31 LOG(ERROR) << "Event::notify -- callback failed";
32 }
33 }
34 }
35 mCondition.notify_all();
36 return Void();
37}
38
39Event::Status Event::poll() {
40 std::lock_guard<std::mutex> lock(mMutex);
41 return mStatus;
42}
43
44Event::Status Event::wait() {
45 std::unique_lock<std::mutex> lock(mMutex);
46 mCondition.wait(lock, [this]{return mStatus != Status::WAITING;});
David Gross0380d7f2017-09-11 16:23:17 -070047 join_thread_locked();
Michael Butler0e2ac1b2017-09-01 10:59:38 -070048 return mStatus;
49}
50
51bool Event::on_finish(std::function<bool(void)> callback) {
52 std::lock_guard<std::mutex> lock(mMutex);
53 if (mCallback != nullptr) {
54 LOG(ERROR) << "Event::on_finish -- a callback has already been bound to this event";
55 return false;
56 }
57 if (callback == nullptr) {
58 LOG(ERROR) << "Event::on_finish -- the new callback is invalid";
59 return false;
60 }
61 mCallback = std::move(callback);
62 return true;
63}
64
65bool Event::bind_thread(std::thread&& asyncThread) {
66 std::lock_guard<std::mutex> lock(mMutex);
67 if (mThread.joinable()) {
68 LOG(ERROR) << "Event::bind_thread -- a thread has already been bound to this event";
69 return false;
70 }
71 if (!asyncThread.joinable()) {
72 LOG(ERROR) << "Event::bind_thread -- the new thread is not joinable";
73 return false;
74 }
75 mThread = std::move(asyncThread);
76 return true;
77}
78
David Gross0380d7f2017-09-11 16:23:17 -070079void Event::join_thread() {
80 std::lock_guard<std::mutex> lock(mMutex);
81 join_thread_locked();
82}
83
84void Event::join_thread_locked() {
85 if (mThread.joinable()) {
86 mThread.join();
87 }
88}
89
Michael Butler0e2ac1b2017-09-01 10:59:38 -070090} // namespace implementation
91} // namespace V1_0
92} // namespace neuralnetworks
93} // namespace hardware
94} // namespace android