| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/worker_pool_mac.h" | 5 #include "base/worker_pool_mac.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #import "base/mac/scoped_nsautorelease_pool.h" |
| 8 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 9 #import "base/scoped_nsautorelease_pool.h" | |
| 10 #include "base/scoped_ptr.h" | 10 #include "base/scoped_ptr.h" |
| 11 #import "base/singleton_objc.h" | 11 #import "base/singleton_objc.h" |
| 12 #include "base/task.h" | 12 #include "base/task.h" |
| 13 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 13 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 14 | 14 |
| 15 // When C++ exceptions are disabled, the C++ library defines |try| and | 15 // When C++ exceptions are disabled, the C++ library defines |try| and |
| 16 // |catch| so as to allow exception-expecting C++ code to build properly when | 16 // |catch| so as to allow exception-expecting C++ code to build properly when |
| 17 // language support for exceptions is not present. These macros interfere | 17 // language support for exceptions is not present. These macros interfere |
| 18 // with the use of |@try| and |@catch| in Objective-C files such as this one. | 18 // with the use of |@try| and |@catch| in Objective-C files such as this one. |
| 19 // Undefine these macros here, after everything has been #included, since | 19 // Undefine these macros here, after everything has been #included, since |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 DCHECK(task_.get()) << "-[TaskOperation main] called with no task"; | 76 DCHECK(task_.get()) << "-[TaskOperation main] called with no task"; |
| 77 if (!task_.get()) { | 77 if (!task_.get()) { |
| 78 return; | 78 return; |
| 79 } | 79 } |
| 80 | 80 |
| 81 { | 81 { |
| 82 AutoLock locked(lock_); | 82 AutoLock locked(lock_); |
| 83 ++running_; | 83 ++running_; |
| 84 } | 84 } |
| 85 | 85 |
| 86 base::ScopedNSAutoreleasePool autoreleasePool; | 86 base::mac::ScopedNSAutoreleasePool autoreleasePool; |
| 87 | 87 |
| 88 @try { | 88 @try { |
| 89 task_->Run(); | 89 task_->Run(); |
| 90 } @catch(NSException* exception) { | 90 } @catch(NSException* exception) { |
| 91 LOG(ERROR) << "-[TaskOperation main] caught an NSException: " | 91 LOG(ERROR) << "-[TaskOperation main] caught an NSException: " |
| 92 << [[exception description] UTF8String]; | 92 << [[exception description] UTF8String]; |
| 93 } @catch(id exception) { | 93 } @catch(id exception) { |
| 94 LOG(ERROR) << "-[TaskOperation main] caught an unknown exception"; | 94 LOG(ERROR) << "-[TaskOperation main] caught an unknown exception"; |
| 95 } | 95 } |
| 96 | 96 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 110 DCHECK(!task_.get()) | 110 DCHECK(!task_.get()) |
| 111 << "-[TaskOperation dealloc] called without running task"; | 111 << "-[TaskOperation dealloc] called without running task"; |
| 112 ANNOTATE_IGNORE_READS_END(); | 112 ANNOTATE_IGNORE_READS_END(); |
| 113 [super dealloc]; | 113 [super dealloc]; |
| 114 } | 114 } |
| 115 | 115 |
| 116 @end // @implementation TaskOperation | 116 @end // @implementation TaskOperation |
| 117 | 117 |
| 118 bool WorkerPool::PostTask(const tracked_objects::Location& from_here, | 118 bool WorkerPool::PostTask(const tracked_objects::Location& from_here, |
| 119 Task* task, bool task_is_slow) { | 119 Task* task, bool task_is_slow) { |
| 120 base::ScopedNSAutoreleasePool autorelease_pool; | 120 base::mac::ScopedNSAutoreleasePool autorelease_pool; |
| 121 | 121 |
| 122 // Ignore |task_is_slow|, it doesn't map directly to any tunable aspect of | 122 // Ignore |task_is_slow|, it doesn't map directly to any tunable aspect of |
| 123 // an NSOperation. | 123 // an NSOperation. |
| 124 | 124 |
| 125 DCHECK(task) << "WorkerPool::PostTask called with no task"; | 125 DCHECK(task) << "WorkerPool::PostTask called with no task"; |
| 126 if (!task) { | 126 if (!task) { |
| 127 return false; | 127 return false; |
| 128 } | 128 } |
| 129 | 129 |
| 130 task->SetBirthPlace(from_here); | 130 task->SetBirthPlace(from_here); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 150 size_t outstanding_delta = 0; | 150 size_t outstanding_delta = 0; |
| 151 size_t running_ops = 0; | 151 size_t running_ops = 0; |
| 152 { | 152 { |
| 153 const base::TimeDelta kCheckPeriod(base::TimeDelta::FromMinutes(10)); | 153 const base::TimeDelta kCheckPeriod(base::TimeDelta::FromMinutes(10)); |
| 154 base::Time now = base::Time::Now(); | 154 base::Time now = base::Time::Now(); |
| 155 | 155 |
| 156 AutoLock locked(lock_); | 156 AutoLock locked(lock_); |
| 157 ++outstanding_; | 157 ++outstanding_; |
| 158 running_ops = running_; | 158 running_ops = running_; |
| 159 if (last_check_.is_null() || now - last_check_ > kCheckPeriod) { | 159 if (last_check_.is_null() || now - last_check_ > kCheckPeriod) { |
| 160 base::ScopedNSAutoreleasePool autoreleasePool; | 160 base::mac::ScopedNSAutoreleasePool autoreleasePool; |
| 161 std::vector<id> ops; | 161 std::vector<id> ops; |
| 162 for (id op in [operation_queue operations]) { | 162 for (id op in [operation_queue operations]) { |
| 163 // DO NOT RETAIN. | 163 // DO NOT RETAIN. |
| 164 ops.push_back(op); | 164 ops.push_back(op); |
| 165 } | 165 } |
| 166 std::sort(ops.begin(), ops.end()); | 166 std::sort(ops.begin(), ops.end()); |
| 167 | 167 |
| 168 outstanding_delta = outstanding_ - ops.size(); | 168 outstanding_delta = outstanding_ - ops.size(); |
| 169 | 169 |
| 170 std::set_intersection(outstanding_ops_.begin(), outstanding_ops_.end(), | 170 std::set_intersection(outstanding_ops_.begin(), outstanding_ops_.end(), |
| 171 ops.begin(), ops.end(), | 171 ops.begin(), ops.end(), |
| 172 std::back_inserter(hung_ops)); | 172 std::back_inserter(hung_ops)); |
| 173 | 173 |
| 174 outstanding_ops_.swap(ops); | 174 outstanding_ops_.swap(ops); |
| 175 last_check_ = now; | 175 last_check_ = now; |
| 176 } | 176 } |
| 177 } | 177 } |
| 178 | 178 |
| 179 // Don't report "nothing to report". | 179 // Don't report "nothing to report". |
| 180 const size_t kUnaccountedOpsDelta = 10; | 180 const size_t kUnaccountedOpsDelta = 10; |
| 181 if (hung_ops.size() > 0 || outstanding_delta > kUnaccountedOpsDelta) { | 181 if (hung_ops.size() > 0 || outstanding_delta > kUnaccountedOpsDelta) { |
| 182 UMA_HISTOGRAM_COUNTS_100("OSX.HungWorkers", hung_ops.size()); | 182 UMA_HISTOGRAM_COUNTS_100("OSX.HungWorkers", hung_ops.size()); |
| 183 UMA_HISTOGRAM_COUNTS_100("OSX.OutstandingDelta", outstanding_delta); | 183 UMA_HISTOGRAM_COUNTS_100("OSX.OutstandingDelta", outstanding_delta); |
| 184 UMA_HISTOGRAM_COUNTS_100("OSX.RunningOps", running_ops); | 184 UMA_HISTOGRAM_COUNTS_100("OSX.RunningOps", running_ops); |
| 185 } | 185 } |
| 186 | 186 |
| 187 return true; | 187 return true; |
| 188 } | 188 } |
| OLD | NEW |