chromium/chrome/browser/ui/tabs/supports_handles.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_TABS_SUPPORTS_HANDLES_H_
#define CHROME_BROWSER_UI_TABS_SUPPORTS_HANDLES_H_

// SupportsHandles is a way to add "handle" support to an object, such as a tab
// or browser window which:
//  - may be transient (i.e. the reference could later become invalid)
//  - needs to be safely referenced from code in other languages, such as
//    JavaScript code in extensions
//
// If you do not need *both* of these, consider a raw or weak pointer instead.
//
// A handle is a semi-opaque value that is safe to store and pass around even
// after the underlying object is destroyed. They behave more or less like weak
// pointers, but have the added benefit that they contain an integral
// `raw_value` which can be copied around, and even passed between programming
// languages.
//
// To use handles with a class, inherit publicly from
// `SupportsHandles<YourClassName>`. Then a handle can be retrieved from an
// instance, and the instance retrieved from the handle:
// ```
//  MyClass::Handle handle = my_object->GetHandle();
//  // Do a bunch of stuff that might delete `my_object`.
//  if (MyClass* obj = handle.Get()) {
//    obj->DoAThing();
//  }
// ```
//
// Notes:
//
// Handle values do not persist across process restart (though restoring handle
// values at startup could be implemented in some future iteration of this
// library.)
//
// Objects with handles may only be generated and retrieved on the primary UI
// thread, though their handles and handle values may be copied to and stored on
// any thread.
//
// The default raw handle type `V` is a 32-bit signed integer, since (a) there
// are usually not more than 4 billion of any UI object, and (b) signed integers
// provide the broadest possible language support. However, you may choose any
// integral type for `V`.
//
// Regardless of choice of `V`, the null value for handles is always zero.
//
// It is a fatal error to try to create a new object if all valid values of `V`
// have already been used. If an object is likely to run through all possible
// values of V (that is, have more than 4 billion constructed over the life of
// a chrome instance) then it is probably a poor candidate for handles (or at
// the very least, you need to pick a larger V).
//
// TODO(dfried, tbergquist): move this file down to c/b/ui if it's used outside
// of the tabstrip.

#include <concepts>
#include <cstdint>
#include <map>

#include "base/check.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"

// Inherit from this type to have your class support handles. Objects that
// support handles cannot be copyable or assignable:
// ```
// class C : public SupportsHandles<C> { ... }
// ```
//
// `V` defines the type (and therefore size in bits) of the underlying handle
// value. A wider value type will provide more unique handle values.
//
// It is required that `T` derive from this class. This constraint is enforced
// via a helper class, as it cannot be enforced before SupportsHandles is
// defined.
template <typename T, std::integral V = int32_t>
class SupportsHandles {};

// The handle type for an object of type `T`.
//
// This is a default-constructable, orderable, comparable, copyable value type.
//
// Unlike WeakPtr there is some overhead in looking up a handle, so convenience
// operators (bool, !, ->, *) are not provided.
template <typename T, std::integral V>
class SupportsHandles<T, V>::Handle {};

class SupportsHandlesTest;

namespace internal {

// Provides handle lookup table storage for each class that supports handles.
//
// This object is strictly sequence-checked and should only ever be accessed
// from the primary UI thread.
template <typename T, std::integral V>
  requires std::derived_from<T, SupportsHandles<T, V>>
class HandleHelper {};

}  // namespace internal

template <typename T, std::integral V>
SupportsHandles<T, V>::SupportsHandles()
    :{}

template <typename T, std::integral V>
SupportsHandles<T, V>::~SupportsHandles() {}

template <typename T, std::integral V>
typename SupportsHandles<T, V>::Handle SupportsHandles<T, V>::GetHandle()
    const {}

template <typename T, std::integral V>
T* SupportsHandles<T, V>::Handle::Get() const {}

#endif  // CHROME_BROWSER_UI_TABS_SUPPORTS_HANDLES_H_