LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-common/base - lifetime.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 17 18 94.4 %
Date: 2026-08-03 02:19:58 Functions: 83 85 97.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef __BASE__LIFETIME_H__
       6             : #define __BASE__LIFETIME_H__
       7             : 
       8             : #include <atomic>
       9             : #include <mutex>
      10             : 
      11             : #include "base/dependency.h"
      12             : #include "base/queue_task.h"
      13             : #include "base/util.h"
      14             : 
      15             : class LifetimeActor;
      16             : class LifetimeManager;
      17             : 
      18             : //
      19             : // The Lifetime management framework enables a structured approach to the
      20             : // problem of tracking inter-dependencies between objects for the purpose
      21             : // of orderly deletion and cleanup.  The dependencies are represented as
      22             : // an acyclic graph with LifetimeActors being the nodes and LifetimeRefs
      23             : // being the links.  The dependency tracker lets us implement "on delete
      24             : // cascade" behavior wherein the deletion of an object triggers deletion
      25             : // of all it's dependents, the dependents' dependents and so on.
      26             : //
      27             : // Each object that requires lifetime management contains an instance of
      28             : // a derived class of LifetimeActor embedded in it. The derived class is
      29             : // specific to the object type and typically contains a back pointer to
      30             : // the object. The convention is to name the derived class as DeleteActor
      31             : // and the instance of it as deleter_.
      32             : //
      33             : // Each managed object (other than the root object) contains one or more
      34             : // LifetimeRef instances.  A LifetimeRef instance corresponds to a parent
      35             : // object on which the object is dependent. The LifetimeRef instances are
      36             : // normally created and linked to the parent objects' LifetimeActor when
      37             : // the managed object is constructed.  Each LifetimeRef contains a back
      38             : // pointer to the managed object.  The convention is to name the members
      39             : // as xxx_delete_ref_, where xxx corresponds to the parent object class.
      40             : //
      41             : // The deletion of a managed object can be triggered by calling Delete on
      42             : // it's actor from any thread. This in turn results in cascaded calls to
      43             : // Delete as described above. Further, the LifetimeActor also enqueues a
      44             : // a delete event to the LifetimeManager for deferred processing.  This
      45             : // event is processed by the LifetimeManager in the desired Task context.
      46             : //
      47             : // When a managed object is destroyed, all the LifetimeRefs to it's parent
      48             : // objects are also destroyed.  This automatically causes the LifetimeRefs
      49             : // to get removed from the list of dependents in the parents' DeleteActor.
      50             : // This in turn also enqueues a delete event to the parent DeleteActor's
      51             : // LifetimeManager if appropriate i.e. if the parent DeleteActor's list of
      52             : // dependents has become empty.
      53             : //
      54             : // The LifetimeManager DeleteExecutor processes delete events for Actors
      55             : // in the context of the desired Task.  It makes sure that there are no
      56             : // dependents and that all relevant state in the DeleteActor's object has
      57             : // been cleaned up i.e. the object may be deleted, before destroying the
      58             : // object.
      59             : //
      60             : // Note that object deletes are triggered from top to bottom while object
      61             : // destruction happens in the reverse order.
      62             : //
      63             : // In addition to having other managed objects as dependents it's common
      64             : // to also have other lightweight objects as dependents. These lightweight
      65             : // dependents should not be tracked using LifetimeRefs, but can instead be
      66             : // tracked using simple reference counts. When the reference count becomes
      67             : // 0, a delete event for the actor should be posted to the LifetimeManager.
      68             : //
      69             : 
      70             : //
      71             : // Base class for a reference to a managed lifetime object.
      72             : //
      73             : class LifetimeRefBase {
      74             : public:
      75             :     LifetimeRefBase(LifetimeActor *actor);
      76             :     virtual ~LifetimeRefBase();
      77             : 
      78             :     // called when the lifetime actor delete is called.
      79             :     // implements "ON DELETE CASCADE" semantics.
      80             :     virtual void Delete() = 0;
      81             : 
      82      709373 :     void Reset(LifetimeActor *actor) {
      83      709373 :         ref_.reset(actor);
      84      709379 :     }
      85             : 
      86             :     bool IsSet() const { return ref_.get() != NULL; }
      87             : 
      88             : private:
      89             :     DependencyRef<LifetimeRefBase, LifetimeActor> ref_;
      90             :     DISALLOW_COPY_AND_ASSIGN(LifetimeRefBase);
      91             : };
      92             : 
      93             : //
      94             : // Class template to create LifetimeRefs for specific object types.
      95             : //
      96             : // Ref is the type of the dependent object.
      97             : // The LifetimeActor parameter is the actor for the parent object.
      98             : //
      99             : template <class Ref>
     100             : class LifetimeRef : public LifetimeRefBase {
     101             : public:
     102     1139171 :     LifetimeRef(Ref *ptr, LifetimeActor *actor)
     103     1139171 :             : LifetimeRefBase(actor), ptr_(ptr) {
     104     1139222 :     }
     105             : 
     106     1047401 :     virtual void Delete() {
     107     1047401 :         ptr_->ManagedDelete();
     108     1047401 :     }
     109             : 
     110             : private:
     111             :     Ref *ptr_;
     112             :     DISALLOW_COPY_AND_ASSIGN(LifetimeRef);
     113             : };
     114             : 
     115             : // Member of an object that has managed lifetime.
     116             : class LifetimeActor {
     117             : public:
     118             :     LifetimeActor(LifetimeManager *manager);
     119             :     virtual ~LifetimeActor();
     120             : 
     121             :     // Trigger the deletion of an object.
     122             :     // May be called from any thread.
     123             :     virtual void Delete();
     124             : 
     125             :     void RetryDelete();
     126             : 
     127             :     // Prevent/Resume deletion of object - for testing only.
     128             :     void PauseDelete();
     129             :     void ResumeDelete();
     130             : 
     131     5053706 :     bool IsDeleted() const { return deleted_; }
     132          48 :     bool HasDependents() const { return !dependents_.empty(); }
     133           0 :     bool HasRefcount() const { return refcount_; }
     134             : 
     135             :     const uint64_t create_time_stamp_usecs() const {
     136             :         return create_time_stamp_usecs_;
     137             :     }
     138       17412 :     const uint64_t delete_time_stamp_usecs() const {
     139       17412 :         return delete_time_stamp_usecs_;
     140             :     }
     141             : 
     142             : private:
     143             :     typedef DependencyList<LifetimeRefBase, LifetimeActor> Dependents;
     144             :     friend class DependencyRef<LifetimeRefBase, LifetimeActor>;
     145             :     friend class LifetimeManager;
     146             : 
     147             :     // Called to check dependencies.
     148             :     virtual bool MayDelete() const = 0;
     149             : 
     150             :     // Called under the manager thread in order to remove the object state.
     151             :     virtual void Shutdown();
     152             : 
     153             :     // Called immediately before the object is destroyed.
     154             :     virtual void DeleteComplete();
     155             : 
     156             :     // Must be called under a specific Task.
     157             :     virtual void Destroy() = 0;
     158             : 
     159             :     void PropagateDelete();
     160             :     void DependencyAdd(DependencyRef<LifetimeRefBase, LifetimeActor> *node);
     161             :     void DependencyRemove(DependencyRef<LifetimeRefBase, LifetimeActor> *node);
     162             : 
     163             :     void ReferenceIncrement();
     164             :     bool ReferenceDecrementAndTest();
     165             : 
     166     2353818 :     bool shutdown_invoked() { return shutdown_invoked_; }
     167     1032058 :     void set_shutdown_invoked() { shutdown_invoked_ = true; }
     168             : 
     169             :     std::mutex mutex_;
     170             :     LifetimeManager *manager_;
     171             :     std::atomic<bool> deleted_;
     172             :     int refcount_;
     173             :     bool shutdown_invoked_;
     174             :     bool delete_paused_;
     175             :     uint64_t create_time_stamp_usecs_;
     176             :     uint64_t delete_time_stamp_usecs_;
     177             :     Dependents dependents_;
     178             : 
     179             :     DISALLOW_COPY_AND_ASSIGN(LifetimeActor);
     180             : };
     181             : 
     182             : //
     183             : // Handles deletion in the correct task context.
     184             : //
     185             : // The pointer to the actor is wrapped inside a LifetimeActorRef to prevent
     186             : // the WorkQueue from deleting the actor.
     187             : //
     188             : class LifetimeManager {
     189             : public:
     190             :     LifetimeManager(int task_id);
     191             :     virtual ~LifetimeManager();
     192             : 
     193             :     // Return the number of times work queue task executions were deferred.
     194           2 :     size_t GetQueueDeferCount() { return defer_count_; }
     195             : 
     196             : protected:
     197             :     virtual void SetQueueDisable(bool disabled);
     198             : 
     199             : private:
     200             :     friend class LifetimeActor;
     201             : 
     202             :     struct LifetimeActorRef {
     203             :         LifetimeActor *actor;
     204             :     };
     205             : 
     206             :     // Enqueue Delete event.
     207             :     void Enqueue(LifetimeActor *actor);
     208             : 
     209             :     // Enqueue Delete event. Used by the actor code which has already
     210             :     // incremented the reference count.
     211             :     void EnqueueNoIncrement(LifetimeActor *actor);
     212             : 
     213             :     // Check if global (not per-actor) conditions for destruction are
     214             :     // satisfied.  Should be over-ridden by derived class if required.
     215      136157 :     virtual bool MayDestroy() { return true; }
     216             : 
     217             :     bool DeleteExecutor(LifetimeActorRef actor_ref);
     218             : 
     219             :     int defer_count_;
     220             :     WorkQueue<LifetimeActorRef> queue_;
     221             : 
     222             :     DISALLOW_COPY_AND_ASSIGN(LifetimeManager);
     223             : };
     224             : 
     225             : #endif

Generated by: LCOV version 1.14