OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lifetime.h
Go to the documentation of this file.
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 <tbb/atomic.h>
9 #include <tbb/mutex.h>
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 //
74 public:
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  void Reset(LifetimeActor *actor) {
83  ref_.reset(actor);
84  }
85 
86  bool IsSet() const { return ref_.get() != NULL; }
87 
88 private:
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  LifetimeRef(Ref *ptr, LifetimeActor *actor)
103  : LifetimeRefBase(actor), ptr_(ptr) {
104  }
105 
106  virtual void Delete() {
107  ptr_->ManagedDelete();
108  }
109 
110 private:
111  Ref *ptr_;
113 };
114 
115 // Member of an object that has managed lifetime.
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  bool IsDeleted() const { return deleted_; }
132  bool HasDependents() const { return !dependents_.empty(); }
133  bool HasRefcount() const { return refcount_; }
134 
135  const uint64_t create_time_stamp_usecs() const {
137  }
138  const uint64_t delete_time_stamp_usecs() const {
140  }
141 
142 private:
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();
162 
163  void ReferenceIncrement();
165 
168 
169  tbb::mutex mutex_;
171  tbb::atomic<bool> deleted_;
178 
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 //
189 public:
190  LifetimeManager(int task_id);
191  virtual ~LifetimeManager();
192 
193  // Return the number of times work queue task executions were deferred.
194  size_t GetQueueDeferCount() { return defer_count_; }
195 
196 protected:
197  virtual void SetQueueDisable(bool disabled);
198 
199 private:
200  friend class LifetimeActor;
201 
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  virtual bool MayDestroy() { return true; }
216 
217  bool DeleteExecutor(LifetimeActorRef actor_ref);
218 
221 
223 };
224 
225 #endif
uint64_t delete_time_stamp_usecs_
Definition: lifetime.h:176
virtual bool MayDestroy()
Definition: lifetime.h:215
LifetimeManager(int task_id)
Definition: lifetime.cc:165
void PropagateDelete()
Definition: lifetime.cc:57
virtual void SetQueueDisable(bool disabled)
Definition: lifetime.cc:179
bool ReferenceDecrementAndTest()
Definition: lifetime.cc:158
virtual ~LifetimeRefBase()
Definition: lifetime.cc:15
virtual ~LifetimeManager()
Definition: lifetime.cc:172
Ref * ptr_
Definition: lifetime.h:111
void Enqueue(LifetimeActor *actor)
Definition: lifetime.cc:188
virtual void Destroy()=0
bool shutdown_invoked_
Definition: lifetime.h:173
LifetimeActor(LifetimeManager *manager)
Definition: lifetime.cc:18
virtual void Shutdown()
Definition: lifetime.cc:92
ObjectType * get() const
Definition: dependency.h:49
bool empty() const
Definition: dependency.h:124
uint64_t create_time_stamp_usecs_
Definition: lifetime.h:175
tbb::atomic< bool > deleted_
Definition: lifetime.h:171
WorkQueue< LifetimeActorRef > queue_
Definition: lifetime.h:220
void ReferenceIncrement()
Definition: lifetime.cc:153
void RetryDelete()
Definition: lifetime.cc:71
void DependencyRemove(DependencyRef< LifetimeRefBase, LifetimeActor > *node)
Definition: lifetime.cc:140
bool delete_paused_
Definition: lifetime.h:174
virtual void Delete()
Definition: lifetime.h:106
virtual void Delete()=0
bool HasRefcount() const
Definition: lifetime.h:133
bool HasDependents() const
Definition: lifetime.h:132
bool IsDeleted() const
Definition: lifetime.h:131
LifetimeManager * manager_
Definition: lifetime.h:170
void Reset(LifetimeActor *actor)
Definition: lifetime.h:82
size_t GetQueueDeferCount()
Definition: lifetime.h:194
bool DeleteExecutor(LifetimeActorRef actor_ref)
Definition: lifetime.cc:214
void set_shutdown_invoked()
Definition: lifetime.h:167
LifetimeRef(Ref *ptr, LifetimeActor *actor)
Definition: lifetime.h:102
virtual bool MayDelete() const =0
void PauseDelete()
Definition: lifetime.cc:101
virtual void DeleteComplete()
Definition: lifetime.cc:81
void DependencyAdd(DependencyRef< LifetimeRefBase, LifetimeActor > *node)
Definition: lifetime.cc:126
bool shutdown_invoked()
Definition: lifetime.h:166
DISALLOW_COPY_AND_ASSIGN(LifetimeManager)
LifetimeRefBase(LifetimeActor *actor)
Definition: lifetime.cc:11
virtual ~LifetimeActor()
Definition: lifetime.cc:26
DISALLOW_COPY_AND_ASSIGN(LifetimeActor)
DependencyRef< LifetimeRefBase, LifetimeActor > ref_
Definition: lifetime.h:89
Dependents dependents_
Definition: lifetime.h:177
virtual void Delete()
Definition: lifetime.cc:38
void EnqueueNoIncrement(LifetimeActor *actor)
Definition: lifetime.cc:195
DependencyList< LifetimeRefBase, LifetimeActor > Dependents
Definition: lifetime.h:143
tbb::mutex mutex_
Definition: lifetime.h:169
DISALLOW_COPY_AND_ASSIGN(LifetimeRef)
DISALLOW_COPY_AND_ASSIGN(LifetimeRefBase)
bool IsSet() const
Definition: lifetime.h:86
const uint64_t delete_time_stamp_usecs() const
Definition: lifetime.h:138
const uint64_t create_time_stamp_usecs() const
Definition: lifetime.h:135
void reset(ObjectType *ptr)
Definition: dependency.h:32
void ResumeDelete()
Definition: lifetime.cc:113