• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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_event_watcher.h"
6 
7 #include <algorithm>
8 
9 #include "base/containers/stack_container.h"
10 #include "base/logging.h"
11 
12 namespace mojo {
13 
SyncEventWatcher(base::WaitableEvent * event,const base::Closure & callback)14 SyncEventWatcher::SyncEventWatcher(base::WaitableEvent* event,
15                                    const base::Closure& callback)
16     : event_(event),
17       callback_(callback),
18       registry_(SyncHandleRegistry::current()),
19       destroyed_(new base::RefCountedData<bool>(false)) {}
20 
~SyncEventWatcher()21 SyncEventWatcher::~SyncEventWatcher() {
22   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
23   if (registered_)
24     registry_->UnregisterEvent(event_, callback_);
25   destroyed_->data = true;
26 }
27 
AllowWokenUpBySyncWatchOnSameThread()28 void SyncEventWatcher::AllowWokenUpBySyncWatchOnSameThread() {
29   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
30   IncrementRegisterCount();
31 }
32 
SyncWatch(const bool ** stop_flags,size_t num_stop_flags)33 bool SyncEventWatcher::SyncWatch(const bool** stop_flags,
34                                  size_t num_stop_flags) {
35   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
36   IncrementRegisterCount();
37   if (!registered_) {
38     DecrementRegisterCount();
39     return false;
40   }
41 
42   // This object may be destroyed during the Wait() call. So we have to preserve
43   // the boolean that Wait uses.
44   auto destroyed = destroyed_;
45 
46   constexpr size_t kFlagStackCapacity = 4;
47   base::StackVector<const bool*, kFlagStackCapacity> should_stop_array;
48   should_stop_array.container().push_back(&destroyed->data);
49   std::copy(stop_flags, stop_flags + num_stop_flags,
50             std::back_inserter(should_stop_array.container()));
51   bool result = registry_->Wait(should_stop_array.container().data(),
52                                 should_stop_array.container().size());
53 
54   // This object has been destroyed.
55   if (destroyed->data)
56     return false;
57 
58   DecrementRegisterCount();
59   return result;
60 }
61 
IncrementRegisterCount()62 void SyncEventWatcher::IncrementRegisterCount() {
63   register_request_count_++;
64   if (!registered_) {
65     registry_->RegisterEvent(event_, callback_);
66     registered_ = true;
67   }
68 }
69 
DecrementRegisterCount()70 void SyncEventWatcher::DecrementRegisterCount() {
71   DCHECK_GT(register_request_count_, 0u);
72   register_request_count_--;
73   if (register_request_count_ == 0 && registered_) {
74     registry_->UnregisterEvent(event_, callback_);
75     registered_ = false;
76   }
77 }
78 
79 }  // namespace mojo
80