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