diff options
Diffstat (limited to 'ipc/chromium/src/mojo/core/ports/port_locker.h')
-rw-r--r-- | ipc/chromium/src/mojo/core/ports/port_locker.h | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/ipc/chromium/src/mojo/core/ports/port_locker.h b/ipc/chromium/src/mojo/core/ports/port_locker.h new file mode 100644 index 0000000000..6a88d14912 --- /dev/null +++ b/ipc/chromium/src/mojo/core/ports/port_locker.h @@ -0,0 +1,90 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_CORE_PORTS_PORT_LOCKER_H_ +#define MOJO_CORE_PORTS_PORT_LOCKER_H_ + +#include <stdint.h> + +#include "base/logging.h" +#include "mojo/core/ports/port_ref.h" + +namespace mojo { +namespace core { +namespace ports { + +class Port; +class PortRef; + +// A helper which must be used to acquire individual Port locks. Any given +// thread may have at most one of these alive at any time. This ensures that +// when multiple ports are locked, they're locked in globally consistent order. +// +// Port locks are acquired upon construction of this object and released upon +// destruction. +class PortLocker { + public: + // Constructs a PortLocker over a sequence of |num_ports| contiguous + // |PortRef*|s. The sequence may be reordered by this constructor, and upon + // return, all referenced ports' locks are held. + PortLocker(const PortRef** port_refs, size_t num_ports); + ~PortLocker(); + + PortLocker(const PortLocker&) = delete; + void operator=(const PortLocker&) = delete; + + // Provides safe access to a PortRef's Port. Note that in release builds this + // doesn't do anything other than pass through to the private accessor on + // |port_ref|, but it does force callers to go through a PortLocker to get to + // the state, thus minimizing the likelihood that they'll go and do something + // stupid. + Port* GetPort(const PortRef& port_ref) const { +#ifdef DEBUG + // Sanity check when DEBUG is on to ensure this is actually a port whose + // lock is held by this PortLocker. + bool is_port_locked = false; + for (size_t i = 0; i < num_ports_ && !is_port_locked; ++i) { + if (port_refs_[i]->port() == port_ref.port()) { + is_port_locked = true; + } + } + DCHECK(is_port_locked); +#endif + return port_ref.port(); + } + +// A helper which can be used to verify that no Port locks are held on the +// current thread. In non-DCHECK builds this is a no-op. +#ifdef DEBUG + static void AssertNoPortsLockedOnCurrentThread(); +#else + static void AssertNoPortsLockedOnCurrentThread() {} +#endif + + private: + const PortRef** const port_refs_; + const size_t num_ports_; +}; + +// Convenience wrapper for a PortLocker that locks a single port. +class SinglePortLocker { + public: + explicit SinglePortLocker(const PortRef* port_ref); + ~SinglePortLocker(); + + SinglePortLocker(const SinglePortLocker&) = delete; + void operator=(const SinglePortLocker&) = delete; + + Port* port() const { return locker_.GetPort(*port_ref_); } + + private: + const PortRef* port_ref_; + PortLocker locker_; +}; + +} // namespace ports +} // namespace core +} // namespace mojo + +#endif // MOJO_CORE_PORTS_PORT_LOCKER_H_ |