blob: b4ce3e8b924c4b047ac5938d77d7d8bddad5e17b [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include <zircon/types.h>
#include <fbl/canary.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>
#include <object/state_observer.h>
#undef TA_GUARDED
#undef TA_REQ
#define TA_GUARDED(args...) /**/
#define TA_REQ(args...) /**/
class Handle;
class CookieJar {
public:
CookieJar() : scope_(ZX_KOID_INVALID), cookie_(0) {}
zx_koid_t scope_;
uint64_t cookie_;
};
class StateTracker {
public:
StateTracker(zx_signals_t signals = 0u) : signals_(signals | ZX_SIGNAL_LAST_HANDLE) { }
StateTracker(const StateTracker& o) = delete;
StateTracker& operator=(const StateTracker& o) = delete;
// Add an observer.
void AddObserver(StateObserver* observer, const StateObserver::CountInfo* cinfo);
// Remove an observer (which must have been added).
void RemoveObserver(StateObserver* observer);
// Called when observers of the handle's state (e.g., waits on the handle) should be
// "cancelled", i.e., when a handle (for the object that owns this StateTracker) is being
// destroyed or transferred. Returns true if at least one observer was found.
bool Cancel(Handle* handle);
// Like Cancel() but issued via via zx_port_cancel().
bool CancelByKey(Handle* handle, const void* port, uint64_t key);
// Notify others of a change in state (possibly waking them). (Clearing satisfied signals or
// setting satisfiable signals should not wake anyone.)
void UpdateState(zx_signals_t clear_mask, zx_signals_t set_mask);
// Nofity others with ZX_SIGNAL_LAST_HANDLE if the value pointed by |count| is 1. This
// value is allowed to mutate by other threads while this call is executing.
void UpdateLastHandleSignal(uint32_t* count);
zx_signals_t GetSignalsState() { return signals_; }
using ObserverList = fbl::DoublyLinkedList<StateObserver*, StateObserverListTraits>;
// Accessors for CookieJars
// These live with the state tracker so they can make use of the state tracker's
// lock (since not all objects have their own locks, but all Dispatchers that are
// cookie-capable have state trackers)
zx_status_t SetCookie(CookieJar* cookiejar, zx_koid_t scope, uint64_t cookie);
zx_status_t GetCookie(CookieJar* cookiejar, zx_koid_t scope, uint64_t* cookie);
zx_status_t InvalidateCookie(CookieJar *cookiejar);
private:
// Returns flag kHandled if one of the observers have been signaled.
StateObserver::Flags UpdateInternalLocked(ObserverList* obs_to_remove, zx_signals_t signals) TA_REQ(lock_);
fbl::Canary<fbl::magic("STRK")> canary_;
zx_signals_t signals_;
fbl::Mutex lock_;
// Active observers are elements in |observers_|.
ObserverList observers_ TA_GUARDED(lock_);
};