1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/public/cpp/bindings/sync_handle_watcher.h"
6
7 #include "base/logging.h"
8
9 namespace mojo {
10
SyncHandleWatcher(const Handle & handle,MojoHandleSignals handle_signals,const SyncHandleRegistry::HandleCallback & callback)11 SyncHandleWatcher::SyncHandleWatcher(
12 const Handle& handle,
13 MojoHandleSignals handle_signals,
14 const SyncHandleRegistry::HandleCallback& callback)
15 : handle_(handle),
16 handle_signals_(handle_signals),
17 callback_(callback),
18 registered_(false),
19 register_request_count_(0),
20 registry_(SyncHandleRegistry::current()),
21 destroyed_(new base::RefCountedData<bool>(false)) {}
22
~SyncHandleWatcher()23 SyncHandleWatcher::~SyncHandleWatcher() {
24 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
25 if (registered_)
26 registry_->UnregisterHandle(handle_);
27
28 destroyed_->data = true;
29 }
30
AllowWokenUpBySyncWatchOnSameThread()31 void SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread() {
32 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
33 IncrementRegisterCount();
34 }
35
SyncWatch(const bool * should_stop)36 bool SyncHandleWatcher::SyncWatch(const bool* should_stop) {
37 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
38 IncrementRegisterCount();
39 if (!registered_) {
40 DecrementRegisterCount();
41 return false;
42 }
43
44 // This object may be destroyed during the Wait() call. So we have to preserve
45 // the boolean that Wait uses.
46 auto destroyed = destroyed_;
47 const bool* should_stop_array[] = {should_stop, &destroyed->data};
48 bool result = registry_->Wait(should_stop_array, 2);
49
50 // This object has been destroyed.
51 if (destroyed->data)
52 return false;
53
54 DecrementRegisterCount();
55 return result;
56 }
57
IncrementRegisterCount()58 void SyncHandleWatcher::IncrementRegisterCount() {
59 register_request_count_++;
60 if (!registered_) {
61 registered_ =
62 registry_->RegisterHandle(handle_, handle_signals_, callback_);
63 }
64 }
65
DecrementRegisterCount()66 void SyncHandleWatcher::DecrementRegisterCount() {
67 DCHECK_GT(register_request_count_, 0u);
68
69 register_request_count_--;
70 if (register_request_count_ == 0 && registered_) {
71 registry_->UnregisterHandle(handle_);
72 registered_ = false;
73 }
74 }
75
76 } // namespace mojo
77