OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lifetime.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "base/lifetime.h"
6 
7 #include <boost/bind.hpp>
8 #include "base/backtrace.h"
9 #include "base/time_util.h"
10 
12  : ref_(this, actor) {
13 }
14 
16 }
17 
19  : manager_(manager), refcount_(0), shutdown_invoked_(false),
20  delete_paused_(false),
21  create_time_stamp_usecs_(UTCTimestampUsec()),
22  delete_time_stamp_usecs_(0) {
23  deleted_ = false;
24 }
25 
27  assert(refcount_ == 0);
28  assert(dependents_.empty());
29 }
30 
31 //
32 // Concurrency: called in the context of any Task or the main thread.
33 //
34 // Used to trigger delete for managed object and it's dependents. Enqueue
35 // this actor to the Lifetime Manager. Propagation of the delete operation
36 // to dependents happens in the context of the LifetimeManager's Task.
37 //
39  tbb::mutex::scoped_lock lock(mutex_);
40  if (deleted_.fetch_and_store(true)) {
41  return;
42  }
44  refcount_++;
46 }
47 
48 //
49 // Concurrency: called in the context of the LifetimeManager's Task.
50 //
51 // Used to propagate delete for a managed object to it's dependents.
52 //
53 // Walk the list of dependent LifetimeRefs and propagate the delete. A mutex is
54 // used to ensure that the dependent list does not change while we are walking
55 // through it.
56 //
58  assert(deleted_);
59  tbb::mutex::scoped_lock lock(mutex_);
61  iter != dependents_.end(); ++iter) {
62  iter->Delete();
63  }
64 }
65 
66 //
67 // Concurrency: called in the context of any Task or the main thread.
68 //
69 // Enqueue a delete event for this actor to the LifetimeManager.
70 //
72  assert(deleted_);
73  manager_->Enqueue(this);
74 }
75 
76 //
77 // Concurrency: called in the context of the LifetimeManager's Task.
78 //
79 // Called immediately before the object is destroyed.
80 //
82 }
83 
84 //
85 // Concurrency: called in the context of the LifetimeManager's Task.
86 //
87 // Can be called multiple times - when the managed object is initially deleted
88 // and whenever a delete event is enqueued to the Lifetime Manager. The latter
89 // happens when the list of dependents becomes empty or the refcount of the
90 // lightweight dependents goes to 0.
91 //
93 }
94 
95 //
96 // Concurrency: called in the context of main thread.
97 // TaskScheduler should be stopped prior to invoking this method.
98 //
99 // Prevent object from getting destroyed - testing only.
100 //
102  tbb::mutex::scoped_lock lock(mutex_);
103  assert(!deleted_);
104  delete_paused_ = true;
105 }
106 
107 //
108 // Concurrency: called in the context of main thread.
109 // TaskScheduler should be stopped prior to invoking this method.
110 //
111 // Allow object to get destroyed - testing only.
112 //
114  tbb::mutex::scoped_lock lock(mutex_);
115  assert(deleted_);
116  delete_paused_ = false;
117  refcount_++;
119 }
120 
121 //
122 // Concurrency: called in the context of any Task.
123 //
124 // Add the LifetimeRef as a dependent for this Actor.
125 //
128  tbb::mutex::scoped_lock lock(mutex_);
129  assert(!deleted_);
130  dependents_.Add(node);
131 }
132 
133 //
134 // Concurrency: called in the context of the LifetimeManager's Task.
135 //
136 // Remove the LifetimeRef as a dependent of this Actor. Note that this can
137 // happen when the dependent object itself is being deleted i.e. this actor
138 // itself need not be marked deleted.
139 //
142  tbb::mutex::scoped_lock lock(mutex_);
143  dependents_.Remove(node);
144  if (deleted_ && dependents_.empty()) {
145  refcount_++;
147  }
148 }
149 
150 // When the actor is placed in the queue the caller must still hold an
151 // "lock" on the object in the form of either a dependency or an
152 // explicit test performed by the derived class MayDelete() method.
154  tbb::mutex::scoped_lock lock(mutex_);
155  refcount_++;
156 }
157 
159  tbb::mutex::scoped_lock lock(mutex_);
160  refcount_--;
161  return (refcount_ == 0 && dependents_.empty() && !delete_paused_ &&
162  MayDelete());
163 }
164 
166  : defer_count_(0),
167  queue_(task_id, 0,
168  boost::bind(&LifetimeManager::DeleteExecutor, this, _1)) {
169  queue_.set_name("LifetimeManager");
170 }
171 
173  queue_.Shutdown();
174 }
175 
176 //
177 // Disable/Enable the WorkQueue - testing only.
178 //
179 void LifetimeManager::SetQueueDisable(bool disabled) {
180  queue_.set_disable(disabled);
181 }
182 
183 //
184 // Concurrency: called in the context of any Task or the main thread.
185 //
186 // Enqueue a delete event for the actor.
187 //
189  LifetimeActorRef actor_ref;
190  actor->ReferenceIncrement();
191  actor_ref.actor = actor;
192  queue_.Enqueue(actor_ref);
193 }
194 
196  LifetimeActorRef actor_ref;
197  actor_ref.actor = actor;
198  queue_.Enqueue(actor_ref);
199 }
200 
201 //
202 // Concurrency: called in the context of the LifetimeManager's Task.
203 //
204 // If this is the first time that the delete actor is being processed, we
205 // propagate the delete to it's dependents and ask the managed object to
206 // shut itself i.e. take care of cleaning up any state not represented as
207 // an explicit LifetimeRef dependent.
208 //
209 // If global conditions for object destruction are not satisfied, enqueue
210 // the delete actor again and defer processing of the queue. Do not bump
211 // up the refcount in this case.
212 // Else go ahead and destroy the object if all conditions are satisfied.
213 //
215  LifetimeActor *actor = actor_ref.actor;
216  assert(actor->IsDeleted());
217  if (!actor->shutdown_invoked()) {
218  actor->PropagateDelete();
219  actor->Shutdown();
220  actor->set_shutdown_invoked();
221  }
222  if (!MayDestroy()) {
223  EnqueueNoIncrement(actor);
224  defer_count_++;
225  return false;
226  }
227  if (actor->ReferenceDecrementAndTest()) {
228  actor->DeleteComplete();
229  actor->Destroy();
230  }
231  return true;
232 }
uint64_t delete_time_stamp_usecs_
Definition: lifetime.h:176
iterator end()
Definition: dependency.h:116
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
void Enqueue(LifetimeActor *actor)
Definition: lifetime.cc:188
virtual void Destroy()=0
LifetimeActor(LifetimeManager *manager)
Definition: lifetime.cc:18
virtual void Shutdown()
Definition: lifetime.cc:92
bool empty() const
Definition: dependency.h:124
tbb::atomic< bool > deleted_
Definition: lifetime.h:171
void Remove(DependencyRef< NodeType, ObjectType > *node)
Definition: dependency.h:102
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
void Add(DependencyRef< NodeType, ObjectType > *node)
Definition: dependency.h:98
bool IsDeleted() const
Definition: lifetime.h:131
LifetimeManager * manager_
Definition: lifetime.h:170
bool DeleteExecutor(LifetimeActorRef actor_ref)
Definition: lifetime.cc:214
void set_shutdown_invoked()
Definition: lifetime.h:167
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
LifetimeRefBase(LifetimeActor *actor)
Definition: lifetime.cc:11
virtual ~LifetimeActor()
Definition: lifetime.cc:26
Dependents dependents_
Definition: lifetime.h:177
virtual void Delete()
Definition: lifetime.cc:38
static uint64_t UTCTimestampUsec()
Definition: time_util.h:13
void EnqueueNoIncrement(LifetimeActor *actor)
Definition: lifetime.cc:195
tbb::mutex mutex_
Definition: lifetime.h:169
iterator begin()
Definition: dependency.h:115
IteratorBase< LifetimeRefBase, typename List::iterator > iterator
Definition: dependency.h:92
void ResumeDelete()
Definition: lifetime.cc:113