Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1085)

Side by Side Diff: athena/resource_manager/resource_manager_impl.cc

Issue 536013002: Decoupling visibility states from webcontent, adding visibility management in ResourceManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "athena/resource_manager/public/resource_manager.h" 5 #include "athena/resource_manager/public/resource_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "athena/activity/public/activity.h" 10 #include "athena/activity/public/activity.h"
11 #include "athena/activity/public/activity_manager.h" 11 #include "athena/activity/public/activity_manager.h"
12 #include "athena/activity/public/activity_manager_observer.h" 12 #include "athena/activity/public/activity_manager_observer.h"
13 #include "athena/resource_manager/memory_pressure_notifier.h" 13 #include "athena/resource_manager/memory_pressure_notifier.h"
14 #include "athena/resource_manager/public/resource_manager_delegate.h" 14 #include "athena/resource_manager/public/resource_manager_delegate.h"
15 #include "athena/wm/public/window_manager.h" 15 #include "athena/wm/public/window_manager.h"
16 #include "athena/wm/public/window_manager_observer.h" 16 #include "athena/wm/public/window_manager_observer.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_ptr.h"
19 #include "ui/aura/window.h" 19 #include "ui/aura/window.h"
20 #include "ui/aura/window_observer.h"
20 21
21 namespace athena { 22 namespace athena {
22 23
23 class ResourceManagerImpl : public ResourceManager, 24 class ResourceManagerImpl : public ResourceManager,
24 public WindowManagerObserver, 25 public WindowManagerObserver,
25 public ActivityManagerObserver, 26 public ActivityManagerObserver,
26 public MemoryPressureObserver { 27 public MemoryPressureObserver,
28 public aura::WindowObserver {
27 public: 29 public:
28 ResourceManagerImpl(ResourceManagerDelegate* delegate); 30 ResourceManagerImpl(ResourceManagerDelegate* delegate);
29 virtual ~ResourceManagerImpl(); 31 virtual ~ResourceManagerImpl();
30 32
31 // ResourceManager: 33 // ResourceManager:
32 virtual void SetMemoryPressureAndStopMonitoring( 34 virtual void SetMemoryPressureAndStopMonitoring(
33 MemoryPressureObserver::MemoryPressure pressure) OVERRIDE; 35 MemoryPressureObserver::MemoryPressure pressure) OVERRIDE;
36 virtual void Pause(bool pause) OVERRIDE {
37 if (pause) {
38 if (!pause_)
39 queued_command_ = false;
40 ++pause_;
41 } else {
42 DCHECK(pause_);
43 --pause_;
44 if (!pause && queued_command_) {
45 UpdateActivityOrder();
46 ManageResource();
47 }
48 }
49 }
34 50
35 // ActivityManagerObserver: 51 // ActivityManagerObserver:
36 virtual void OnActivityStarted(Activity* activity) OVERRIDE; 52 virtual void OnActivityStarted(Activity* activity) OVERRIDE;
37 virtual void OnActivityEnding(Activity* activity) OVERRIDE; 53 virtual void OnActivityEnding(Activity* activity) OVERRIDE;
38 54
39 // WindowManagerObserver: 55 // WindowManagerObserver:
40 virtual void OnOverviewModeEnter() OVERRIDE; 56 virtual void OnOverviewModeEnter() OVERRIDE;
41 virtual void OnOverviewModeExit() OVERRIDE; 57 virtual void OnOverviewModeExit() OVERRIDE;
42 virtual void OnActivityOrderHasChanged() OVERRIDE; 58 virtual void OnSplitViewModeEnter() OVERRIDE;
59 virtual void OnSplitViewModeExit() OVERRIDE;
43 60
44 // MemoryPressureObserver: 61 // MemoryPressureObserver:
45 virtual void OnMemoryPressure( 62 virtual void OnMemoryPressure(
46 MemoryPressureObserver::MemoryPressure pressure) OVERRIDE; 63 MemoryPressureObserver::MemoryPressure pressure) OVERRIDE;
47 virtual ResourceManagerDelegate* GetDelegate() OVERRIDE; 64 virtual ResourceManagerDelegate* GetDelegate() OVERRIDE;
48 65
66 // aura::WindowObserver:
67 virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE;
68
49 private: 69 private:
50 // Manage the resources for our activities. 70 // Manage the resources for our activities.
51 void ManageResource(); 71 void ManageResource();
52 72
53 // Order our activity list to the order of activities of the stream. 73 // Order our activity list to the order of activities of the stream.
54 // TODO(skuhne): Once the ActivityManager is responsible to create this list 74 // TODO(skuhne): Once the ActivityManager is responsible to create this list
55 // for us, we can remove this code here. 75 // for us, we can remove this code here.
56 void UpdateActivityOrder(); 76 void UpdateActivityOrder();
57 77
58 // The sorted (new(front) -> old(back)) activity list. 78 // The sorted (new(front) -> old(back)) activity list.
59 // TODO(skuhne): Once the ActivityManager is responsible to create this list 79 // TODO(skuhne): Once the ActivityManager is responsible to create this list
60 // for us, we can remove this code here. 80 // for us, we can remove this code here.
61 std::vector<Activity*> activity_list_; 81 std::vector<Activity*> activity_list_;
62 82
63 // The resource manager delegate. 83 // The resource manager delegate.
64 scoped_ptr<ResourceManagerDelegate> delegate_; 84 scoped_ptr<ResourceManagerDelegate> delegate_;
65 85
66 // Keeping a reference to the current memory pressure. 86 // Keeping a reference to the current memory pressure.
67 MemoryPressureObserver::MemoryPressure current_memory_pressure_; 87 MemoryPressureObserver::MemoryPressure current_memory_pressure_;
68 88
69 // The memory pressure notifier. 89 // The memory pressure notifier.
70 scoped_ptr<MemoryPressureNotifier> memory_pressure_notifier_; 90 scoped_ptr<MemoryPressureNotifier> memory_pressure_notifier_;
71 91
92 // A ref counter. As long as not 0, the management is on hold.
93 int pause_;
94
95 // If true, a command came in while the resource manager was paused.
96 bool queued_command_;
97
98 // Used by ManageResource() to determine an activity state change while it
99 // changes Activity properties.
100 bool activity_order_changed_;
101
102 // True if in overview mode - activity order changes will be ignored if true
103 // and postponed till after the overview mode is ending.
104 bool in_overview_mode_;
105
106 // True if we are in split view mode.
107 bool in_splitview_mode_;
108
72 DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl); 109 DISALLOW_COPY_AND_ASSIGN(ResourceManagerImpl);
73 }; 110 };
74 111
75 namespace { 112 namespace {
76 ResourceManagerImpl* instance = NULL; 113 ResourceManagerImpl* instance = NULL;
114
115 // We allow this many activities to be visible. All others must be at state of
116 // invisible or below.
117 const int kMaxVisibleActivities = 3;
118
77 } // namespace 119 } // namespace
78 120
79 ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate) 121 ResourceManagerImpl::ResourceManagerImpl(ResourceManagerDelegate* delegate)
80 : delegate_(delegate), 122 : delegate_(delegate),
81 current_memory_pressure_(MemoryPressureObserver::MEMORY_PRESSURE_UNKNOWN), 123 current_memory_pressure_(MemoryPressureObserver::MEMORY_PRESSURE_UNKNOWN),
82 memory_pressure_notifier_(new MemoryPressureNotifier(this)) { 124 memory_pressure_notifier_(new MemoryPressureNotifier(this)),
125 pause_(false),
126 queued_command_(false),
127 activity_order_changed_(false),
128 in_overview_mode_(false),
129 in_splitview_mode_(false) {
83 WindowManager::GetInstance()->AddObserver(this); 130 WindowManager::GetInstance()->AddObserver(this);
84 ActivityManager::Get()->AddObserver(this); 131 ActivityManager::Get()->AddObserver(this);
85 } 132 }
86 133
87 ResourceManagerImpl::~ResourceManagerImpl() { 134 ResourceManagerImpl::~ResourceManagerImpl() {
88 ActivityManager::Get()->RemoveObserver(this); 135 ActivityManager::Get()->RemoveObserver(this);
89 WindowManager::GetInstance()->RemoveObserver(this); 136 WindowManager::GetInstance()->RemoveObserver(this);
137
138 while (!activity_list_.empty())
139 OnActivityEnding(activity_list_.front());
90 } 140 }
91 141
92 void ResourceManagerImpl::SetMemoryPressureAndStopMonitoring( 142 void ResourceManagerImpl::SetMemoryPressureAndStopMonitoring(
93 MemoryPressureObserver::MemoryPressure pressure) { 143 MemoryPressureObserver::MemoryPressure pressure) {
94 memory_pressure_notifier_->StopObserving(); 144 memory_pressure_notifier_->StopObserving();
95 OnMemoryPressure(pressure); 145 OnMemoryPressure(pressure);
96 } 146 }
97 147
98 void ResourceManagerImpl::OnActivityStarted(Activity* activity) { 148 void ResourceManagerImpl::OnActivityStarted(Activity* activity) {
99 // As long as we have to manage the list of activities ourselves, we need to 149 // As long as we have to manage the list of activities ourselves, we need to
100 // order it here. 150 // order it here.
101 activity_list_.push_back(activity); 151 activity_list_.push_back(activity);
102 UpdateActivityOrder(); 152 UpdateActivityOrder();
103 // Update the activity states. 153 // Update the activity states.
104 ManageResource(); 154 ManageResource();
155 // Remember that the activity order has changed.
156 activity_order_changed_ = true;
157 activity->GetWindow()->AddObserver(this);
105 } 158 }
106 159
107 void ResourceManagerImpl::OnActivityEnding(Activity* activity) { 160 void ResourceManagerImpl::OnActivityEnding(Activity* activity) {
161 DCHECK(activity->GetWindow());
162 activity->GetWindow()->RemoveObserver(this);
108 // Remove the activity from the list again. 163 // Remove the activity from the list again.
109 std::vector<Activity*>::iterator it = 164 std::vector<Activity*>::iterator it =
110 std::find(activity_list_.begin(), activity_list_.end(), activity); 165 std::find(activity_list_.begin(), activity_list_.end(), activity);
111 DCHECK(it != activity_list_.end()); 166 DCHECK(it != activity_list_.end());
112 activity_list_.erase(it); 167 activity_list_.erase(it);
168 // Remember that the activity order has changed.
169 activity_order_changed_ = true;
113 } 170 }
114 171
115 void ResourceManagerImpl::OnOverviewModeEnter() { 172 void ResourceManagerImpl::OnOverviewModeEnter() {
116 // Nothing to do here. 173 in_overview_mode_ = true;
117 } 174 }
118 175
119 void ResourceManagerImpl::OnOverviewModeExit() { 176 void ResourceManagerImpl::OnOverviewModeExit() {
120 // Nothing to do here. 177 in_overview_mode_ = false;
178 // Reorder the activities.
179 UpdateActivityOrder();
121 } 180 }
122 181
123 void ResourceManagerImpl::OnActivityOrderHasChanged() { 182 void ResourceManagerImpl::OnSplitViewModeEnter() {
183 // Re-apply the memory pressure to make sure enough items are visible.
184 in_splitview_mode_ = true;
185 ManageResource();
186 }
187
188
189 void ResourceManagerImpl::OnSplitViewModeExit() {
190 // We don't do immediately something yet. The next ManageResource call will
191 // come soon.
192 in_splitview_mode_ = false;
193 }
194
195 void ResourceManagerImpl::OnWindowStackingChanged(aura::Window* window) {
196 // TODO(skuhne): This needs to be changed to some WindowListProvider observer
197 // if we decouple window order from activity order.
198
199 // No need to do anything while being in overview mode.
200 if (in_overview_mode_)
201 return;
202
124 // As long as we have to manage the list of activities ourselves, we need to 203 // As long as we have to manage the list of activities ourselves, we need to
125 // order it here. 204 // order it here.
126 UpdateActivityOrder(); 205 UpdateActivityOrder();
206
127 // Manage the resources of each activity. 207 // Manage the resources of each activity.
128 ManageResource(); 208 ManageResource();
129 } 209 }
130 210
131 void ResourceManagerImpl::OnMemoryPressure( 211 void ResourceManagerImpl::OnMemoryPressure(
132 MemoryPressureObserver::MemoryPressure pressure) { 212 MemoryPressureObserver::MemoryPressure pressure) {
133 current_memory_pressure_ = pressure; 213 current_memory_pressure_ = pressure;
134 ManageResource(); 214 ManageResource();
135 } 215 }
136 216
137 ResourceManagerDelegate* ResourceManagerImpl::GetDelegate() { 217 ResourceManagerDelegate* ResourceManagerImpl::GetDelegate() {
138 return delegate_.get(); 218 return delegate_.get();
139 } 219 }
140 220
141 void ResourceManagerImpl::ManageResource() { 221 void ResourceManagerImpl::ManageResource() {
142 // If there is none or only one app running we cannot do anything. 222 // If there is none or only one app running we cannot do anything.
143 if (activity_list_.size() <= 1U) 223 if (activity_list_.size() <= 1U)
144 return; 224 return;
225
226 if (pause_) {
227 queued_command_ = true;
228 return;
229 }
230
145 // TODO(skuhne): This algorithm needs to take all kinds of predictive analysis 231 // TODO(skuhne): This algorithm needs to take all kinds of predictive analysis
146 // and running applications into account. For this first patch we only do a 232 // and running applications into account. For this first patch we only do a
147 // very simple "floating window" algorithm which is surely not good enough. 233 // very simple "floating window" algorithm which is surely not good enough.
148 size_t max_running_activities = 5; 234 size_t max_running_activities = 5;
149 switch (current_memory_pressure_) { 235 switch (current_memory_pressure_) {
150 case MEMORY_PRESSURE_UNKNOWN: 236 case MEMORY_PRESSURE_UNKNOWN:
151 // If we do not know how much memory we have we assume that it must be a 237 // If we do not know how much memory we have we assume that it must be a
152 // high consumption. 238 // high consumption.
153 // Fallthrough. 239 // Fallthrough.
154 case MEMORY_PRESSURE_HIGH: 240 case MEMORY_PRESSURE_HIGH:
155 max_running_activities = 5; 241 max_running_activities = 5;
156 break; 242 break;
157 case MEMORY_PRESSURE_CRITICAL: 243 case MEMORY_PRESSURE_CRITICAL:
158 max_running_activities = 0; 244 max_running_activities = 0;
159 break; 245 break;
160 case MEMORY_PRESSURE_MODERATE: 246 case MEMORY_PRESSURE_MODERATE:
161 max_running_activities = 7; 247 max_running_activities = 7;
162 break; 248 break;
163 case MEMORY_PRESSURE_LOW: 249 case MEMORY_PRESSURE_LOW:
164 // No need to do anything yet. 250 // This doesn't really matter. We do not change anything but turning
165 return; 251 // activities visible.
252 max_running_activities = 10000;
253 break;
166 } 254 }
255
256 // The first n activities should be trated as "visible", means they updated
257 // in overview mode and will keep their layer resources for faster switch
258 // times. Usually we use |kMaxVisibleActivities| items, but when the memory
259 // pressure gets critical we only hold as many as are really visible.
260 size_t max_activities = kMaxVisibleActivities;
261 if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL)
262 max_activities = 1 + (in_splitview_mode_ ? 1 : 0);
263
264 // Restart and / or bail if the order of activities changes due to our calls.
265 activity_order_changed_ = false;
266
267 // Change the visibility of our activities in a pre-processing step. This is
268 // required since it might change the order/number of activities.
269 size_t index = 0;
270 while (index < activity_list_.size()) {
271 Activity* activity = activity_list_[index];
272 Activity::ActivityState state = activity->GetCurrentState();
273
274 // The first |kMaxVisibleActivities| entries should be visible, all others
275 // invisible or at a lower activity state.
276 if (index < max_activities ||
277 (state == Activity::ACTIVITY_INVISIBLE ||
278 state == Activity::ACTIVITY_VISIBLE)) {
279 Activity::ActivityState visiblity_state =
280 index < max_activities ? Activity::ACTIVITY_VISIBLE :
281 Activity::ACTIVITY_INVISIBLE;
282 // Only change the state when it changes. Note that when the memory
283 // pressure is critical, only the primary activities (1 or 2) are made
284 // visible. Furthermore, in relaxed mode we only want to make visible.
285 if (visiblity_state != state &&
286 (current_memory_pressure_ != MEMORY_PRESSURE_LOW ||
287 visiblity_state == Activity::ACTIVITY_VISIBLE))
288 activity->SetCurrentState(visiblity_state);
289 }
290
291 // See which index we should handle next.
292 if (activity_order_changed_) {
293 activity_order_changed_ = false;
294 index = 0;
295 } else {
296 ++index;
297 }
298 }
299
300 // No need to remove anything.
301 if (current_memory_pressure_ == MEMORY_PRESSURE_LOW)
302 return;
303
304 // Check if/which activity we want to unload.
167 Activity* oldest_media_activity = NULL; 305 Activity* oldest_media_activity = NULL;
168 std::vector<Activity*> unloadable_activities; 306 std::vector<Activity*> unloadable_activities;
169 for (std::vector<Activity*>::iterator it = activity_list_.begin(); 307 for (std::vector<Activity*>::iterator it = activity_list_.begin();
170 it != activity_list_.end(); ++it) { 308 it != activity_list_.end(); ++it) {
171 // The activity should not be unloaded or visible. 309 Activity::ActivityState state = (*it)->GetCurrentState();
172 if ((*it)->GetCurrentState() != Activity::ACTIVITY_UNLOADED && 310 // The activity should neither be unloaded nor visible.
173 !(*it)->IsVisible()) { 311 if (state != Activity::ACTIVITY_UNLOADED &&
312 state != Activity::ACTIVITY_VISIBLE) {
174 if ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) { 313 if ((*it)->GetMediaState() == Activity::ACTIVITY_MEDIA_STATE_NONE) {
175 // Does not play media - so we can unload this immediately. 314 // Does not play media - so we can unload this immediately.
176 unloadable_activities.push_back(*it); 315 unloadable_activities.push_back(*it);
177 } else { 316 } else {
178 oldest_media_activity = *it; 317 oldest_media_activity = *it;
179 } 318 }
180 } 319 }
181 } 320 }
321
182 if (unloadable_activities.size() > max_running_activities) { 322 if (unloadable_activities.size() > max_running_activities) {
183 unloadable_activities.back()->SetCurrentState(Activity::ACTIVITY_UNLOADED); 323 unloadable_activities.back()->SetCurrentState(Activity::ACTIVITY_UNLOADED);
184 return; 324 return;
185 } else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) { 325 } else if (current_memory_pressure_ == MEMORY_PRESSURE_CRITICAL) {
186 if (oldest_media_activity) { 326 if (oldest_media_activity) {
187 oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED); 327 oldest_media_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED);
328 LOG(WARNING) << "Unloading item to releave critical memory pressure";
188 return; 329 return;
189 } 330 }
190 LOG(ERROR) << "[ResourceManager]: Single activity uses too much memory."; 331 LOG(ERROR) << "[ResourceManager]: Single activity uses too much memory.";
191 return; 332 return;
192 } 333 }
334
193 if (current_memory_pressure_ != MEMORY_PRESSURE_UNKNOWN) { 335 if (current_memory_pressure_ != MEMORY_PRESSURE_UNKNOWN) {
194 // Only show this warning when the memory pressure is actually known. This 336 // Only show this warning when the memory pressure is actually known. This
195 // will suppress warnings in e.g. unit tests. 337 // will suppress warnings in e.g. unit tests.
196 LOG(WARNING) << "[ResourceManager]: No way to release memory pressure (" << 338 LOG(WARNING) << "[ResourceManager]: No way to release memory pressure (" <<
197 current_memory_pressure_ << 339 current_memory_pressure_ <<
198 "), Activities (running, allowed, unloadable)=(" << 340 "), Activities (running, allowed, unloadable)=(" <<
199 activity_list_.size() << ", " << 341 activity_list_.size() << ", " <<
200 max_running_activities << ", " << 342 max_running_activities << ", " <<
201 unloadable_activities.size() << ")"; 343 unloadable_activities.size() << ")";
202 } 344 }
203 } 345 }
204 346
205 void ResourceManagerImpl::UpdateActivityOrder() { 347 void ResourceManagerImpl::UpdateActivityOrder() {
348 queued_command_ = true;
206 if (activity_list_.empty()) 349 if (activity_list_.empty())
207 return; 350 return;
208 std::vector<Activity*> new_activity_list; 351 std::vector<Activity*> new_activity_list;
209 const aura::Window::Windows children = 352 const aura::Window::Windows children =
210 activity_list_[0]->GetWindow()->parent()->children(); 353 activity_list_[0]->GetWindow()->parent()->children();
211 // Find the first window in the container which is part of the application. 354 // Find the first window in the container which is part of the application.
212 for (aura::Window::Windows::const_iterator child_iterator = children.begin(); 355 for (aura::Window::Windows::const_reverse_iterator child_iterator =
213 child_iterator != children.end(); ++child_iterator) { 356 children.rbegin();
357 child_iterator != children.rend(); ++child_iterator) {
214 for (std::vector<Activity*>::iterator activity_iterator = 358 for (std::vector<Activity*>::iterator activity_iterator =
215 activity_list_.begin(); 359 activity_list_.begin();
216 activity_iterator != activity_list_.end(); ++activity_iterator) { 360 activity_iterator != activity_list_.end(); ++activity_iterator) {
217 if (*child_iterator == (*activity_iterator)->GetWindow()) { 361 if (*child_iterator == (*activity_iterator)->GetWindow()) {
218 new_activity_list.push_back(*activity_iterator); 362 new_activity_list.push_back(*activity_iterator);
219 activity_list_.erase(activity_iterator); 363 activity_list_.erase(activity_iterator);
220 break; 364 break;
221 } 365 }
222 } 366 }
223 } 367 }
224 // At this point the old list should be empty and we can swap the lists. 368 // At this point the old list should be empty and we can swap the lists.
225 DCHECK(!activity_list_.size()); 369 DCHECK(!activity_list_.size());
226 activity_list_ = new_activity_list; 370 activity_list_ = new_activity_list;
371
372 // Remember that the activity order has changed.
373 activity_order_changed_ = true;
227 } 374 }
228 375
229 // static 376 // static
230 void ResourceManager::Create() { 377 void ResourceManager::Create() {
231 DCHECK(!instance); 378 DCHECK(!instance);
232 instance = new ResourceManagerImpl( 379 instance = new ResourceManagerImpl(
233 ResourceManagerDelegate::CreateResourceManagerDelegate()); 380 ResourceManagerDelegate::CreateResourceManagerDelegate());
234 } 381 }
235 382
236 // static 383 // static
237 ResourceManager* ResourceManager::Get() { 384 ResourceManager* ResourceManager::Get() {
238 return instance; 385 return instance;
239 } 386 }
240 387
241 // static 388 // static
242 void ResourceManager::Shutdown() { 389 void ResourceManager::Shutdown() {
243 DCHECK(instance); 390 DCHECK(instance);
244 delete instance; 391 delete instance;
245 instance = NULL; 392 instance = NULL;
246 } 393 }
247 394
248 ResourceManager::ResourceManager() {} 395 ResourceManager::ResourceManager() {}
249 396
250 ResourceManager::~ResourceManager() { 397 ResourceManager::~ResourceManager() {
251 DCHECK(instance); 398 DCHECK(instance);
252 instance = NULL; 399 instance = NULL;
253 } 400 }
254 401
255 } // namespace athena 402 } // namespace athena
OLDNEW
« no previous file with comments | « athena/resource_manager/public/resource_manager.h ('k') | athena/resource_manager/resource_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698