/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <atomic> #include <memory> #include <glog/logging.h> #include <folly/CPortability.h> #include <folly/Portability.h> #include <folly/concurrency/CacheLocality.h> #include <folly/synchronization/Hazptr-fwd.h> #include <folly/synchronization/detail/HazptrUtils.h> /// /// Classes related to objects protectable by hazard pointers. /// namespace folly { /** * hazptr_obj * * Private base class for objects protectable by hazard pointers. * * Data members: * - next_: link to next object in private singly linked lists. * - reclaim_: reclamation function for this object. * - cohort_tag_: A pointer to a cohort (where the object is to be * pushed when retired). It can also be used as a tag (see * below). * * Cohorts, Tags, Tagged Objects, and Untagged Objects: * * - Cohorts: Cohorts (instances of hazptr_obj_cohort) are sets of * retired hazptr_obj-s. Cohorts are used to keep related objects * together instead of being spread across thread local structures * and/or mixed with unrelated objects. * * - Tags: A tag is a unique identifier used for fast identification * of related objects for synchronous reclamation. Tags are * implemented as addresses of cohorts, with the lowest bit set (to * save the space of separate cohort and tag data members and to * differentiate from cohorts of untagged objects. * * - Tagged objects: Objects are tagged for fast identification. The * primary use case is for synchronous reclamation ((e.g., the * destruction of all Key and Value objects that were part of a * Folly ConcurrentHashMap instance). Member function * set_cohort_tag makes an object tagged. * * - Untagged objects: Objects that do not need to be identified * separately from unrelated objects are not tagged (to keep tagged * objects uncluttered). Untagged objects may or may not be * associated with cohorts. An example of untagged objects * associated with cohorts are Segment-s of Folly UnboundedQueue. * Although such objects do not need synchronous reclamation, * keeping them in cohorts helps avoid cases of a few missing * objects delaying the reclamation of large numbers of * link-counted objects. Objects are untagged either by default or * after calling set_cohort_no_tag. * * - Thread Safety: Member functions set_cohort_tag and * set_cohort_no_tag are not thread-safe. Thread safety must be * ensured by the calling thread. */ template <template <typename> class Atom> class hazptr_obj { … }; // hazptr_obj /** * hazptr_obj_list * * List of hazptr_obj-s. */ template <template <typename> class Atom> class hazptr_obj_list { … }; // hazptr_obj_list /** * hazptr_obj_cohort * * List of retired objects. For objects to be retred to a cohort, * either of the hazptr_obj member functions set_cohort_tag or * set_cohort_no_tag needs to be called before the object is retired. * * See description of hazptr_obj for notes on cohorts, tags, and * tageed and untagged objects. * * [Note: For now supports only the default domain.] */ template <template <typename> class Atom> class hazptr_obj_cohort { … }; // hazptr_obj_cohort /** * hazptr_obj_retired_list * * Used for maintaining lists of retired objects in domain * structure. Locked operations are used for lists of tagged * objects. Unlocked operations are used for the untagged list. */ /** hazptr_obj_retired_list */ template <template <typename> class Atom> class hazptr_obj_retired_list { … }; // hazptr_obj_retired_list /** * hazptr_deleter * * For empty base optimization. */ template <typename T, typename D> class hazptr_deleter { … }; hazptr_deleter<T, std::default_delete<T>>; /** * hazptr_obj_base * * Base template for objects protected by hazard pointers. */ template <typename T, template <typename> class Atom, typename D> class hazptr_obj_base : public hazptr_obj<Atom>, public hazptr_deleter<T, D> { … }; // hazptr_obj_base } // namespace folly