blob: d9fdfdf2ff8580480dede6d2474fe0daaf231c20 [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 LIB_FIDL_CPP_INTERNAL_WEAK_STUB_CONTROLLER_H_
#define LIB_FIDL_CPP_INTERNAL_WEAK_STUB_CONTROLLER_H_
#include <stdint.h>
#include <threads.h>
#include <zircon/assert.h>
#include <atomic>
namespace fidl {
namespace internal {
class StubController;
// A weak reference to a |StubController|.
//
// Used to link a |PendingResponse| object with a |StubController|. When the
// |StubController| is destroyed (or unbound from the underling channel), the
// weak reference is invalidated, preventing outstanding |PendingResponse|
// objects from referencing the |StubController|.
class WeakStubController final {
public:
// Creates a weak reference to a |StubController|.
//
// The created |WeakStubController| has a reference count of one, which means
// the creator is responsible for calling |Release| exactly once.
explicit WeakStubController(StubController* controller);
// Increment the refernence count for this object.
//
// Each call to this method imposes a requirement to eventually call |Release|
// exactly once.
void AddRef();
// Decrements the reference count for this object.
//
// When the reference count reaches zero, the object is destroyed.
void Release();
// Break the connection between this object and the |StubController|.
//
// After calling this method, |controller()| will return nullptr.
// Cannot be called concurrently with AddRef or Release.
void Invalidate();
// The |StubController| to which this weak reference refers.
//
// After the weak reference has been invalidated, this method returns nullptr.
// Cannot be called concurrently with AddRef or Release.
StubController* controller() const;
private:
~WeakStubController();
// Starts at one. This is atomic so that PendingResponse objects can be deleted
// on any thread. See fxrev.dev/437828 for a longer discussion.
std::atomic<uint32_t> ref_count_;
StubController* controller_;
#if ZX_DEBUG_ASSERT_IMPLEMENTED
// thrd_current() needs to match the thread on which this instance was
// created, so that non-atomic ref_count_ updates work as intended.
bool IsCurrentThreadOk() const;
#endif
// If the WeakStubController constructor is release build, this field will be initialized to
// thrd_t{} by the constructor and stay that value until destruction. If debug build, this field
// remembers the construction thread. In a debug build, non-thread-safe methods will ZX_PANIC()
// if run on a thread other than the construction thread AND thread != thrd_t{}. By checking vs.
// thrd_t{}, a WeakStubController constructed by release code, but passed to a debug method, will
// avoid asserting.
thrd_t thread_;
};
} // namespace internal
} // namespace fidl
#endif // LIB_FIDL_CPP_INTERNAL_WEAK_STUB_CONTROLLER_H_