#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
namespace mojo {
SyncHandleWatcher::SyncHandleWatcher(
const Handle& handle,
MojoHandleSignals handle_signals,
const SyncHandleRegistry::HandleCallback& callback)
: handle_(handle),
handle_signals_(handle_signals),
callback_(callback),
registered_(false),
register_request_count_(0),
registry_(SyncHandleRegistry::current()),
destroyed_(base::MakeRefCounted<base::RefCountedData<bool>>(false)) {}
SyncHandleWatcher::~SyncHandleWatcher() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (registered_)
registry_->UnregisterHandle(handle_);
destroyed_->data = true;
}
void SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IncrementRegisterCount();
}
bool SyncHandleWatcher::SyncWatch(const bool* should_stop) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IncrementRegisterCount();
if (!registered_) {
DecrementRegisterCount();
return false;
}
auto destroyed = destroyed_;
const bool* should_stop_array[] = {should_stop, &destroyed->data};
bool result = registry_->Wait(should_stop_array);
if (destroyed->data)
return false;
DecrementRegisterCount();
return result;
}
void SyncHandleWatcher::IncrementRegisterCount() {
register_request_count_++;
if (!registered_) {
registered_ =
registry_->RegisterHandle(handle_, handle_signals_, callback_);
}
}
void SyncHandleWatcher::DecrementRegisterCount() {
DCHECK_GT(register_request_count_, 0u);
register_request_count_--;
if (register_request_count_ == 0 && registered_) {
registry_->UnregisterHandle(handle_);
registered_ = false;
}
}
}