Index: base/profiler/stack_sampling_profiler.cc |
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc |
index f7605079953769e162aa7463ebc54c6ea772485a..c5c284763fcd1ea708ca33c067e675085f907f93 100644 |
--- a/base/profiler/stack_sampling_profiler.cc |
+++ b/base/profiler/stack_sampling_profiler.cc |
@@ -19,49 +19,94 @@ namespace base { |
namespace { |
-// Thread-safe singleton class that stores collected profiles waiting to be |
-// processed. |
-class PendingProfiles { |
+// Singleton class responsible for providing the default processing for profiles |
+// (i.e. for profiles generated by profilers without their own completed |
+// callback). |
+class DefaultProfileProcessor { |
public: |
- PendingProfiles(); |
- ~PendingProfiles(); |
+ using CompletedCallback = StackSamplingProfiler::CompletedCallback; |
- static PendingProfiles* GetInstance(); |
+ DefaultProfileProcessor(); |
+ ~DefaultProfileProcessor(); |
- // Appends |profiles|. This function is thread safe. |
- void PutProfiles(const std::vector<StackSamplingProfiler::Profile>& profiles); |
- // Gets the pending profiles into *|profiles|. This function is thread safe. |
- void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles); |
+ static DefaultProfileProcessor* GetInstance(); |
+ |
+ // Sets the callback to use for processing profiles captured without a |
+ // per-profiler completed callback. Pending completed profiles are stored in |
+ // this object until a non-null callback is provided here. This function is |
+ // thread-safe. |
+ void SetCompletedCallback(CompletedCallback callback); |
+ |
+ // Processes |profiles|. This function is thread safe. |
+ void ProcessProfiles( |
+ const std::vector<StackSamplingProfiler::Profile>& profiles); |
private: |
+ // Gets the pending profiles into *|profiles|, with proper locking. |
+ void GetProfiles(std::vector<StackSamplingProfiler::Profile>* profiles); |
+ |
+ // Gets the current completed callback, with proper locking. |
+ CompletedCallback GetCompletedCallback() const; |
+ |
+ mutable Lock callback_lock_; |
+ CompletedCallback default_completed_callback_; |
+ |
Lock profiles_lock_; |
std::vector<StackSamplingProfiler::Profile> profiles_; |
- DISALLOW_COPY_AND_ASSIGN(PendingProfiles); |
+ DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor); |
}; |
-PendingProfiles::PendingProfiles() {} |
+DefaultProfileProcessor::DefaultProfileProcessor() {} |
-PendingProfiles::~PendingProfiles() {} |
+DefaultProfileProcessor::~DefaultProfileProcessor() {} |
// static |
-PendingProfiles* PendingProfiles::GetInstance() { |
- return Singleton<PendingProfiles>::get(); |
+DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() { |
+ return Singleton<DefaultProfileProcessor>::get(); |
} |
-void PendingProfiles::PutProfiles( |
+void DefaultProfileProcessor::SetCompletedCallback(CompletedCallback callback) { |
+ { |
+ AutoLock scoped_lock(callback_lock_); |
+ default_completed_callback_ = callback; |
+ } |
+ |
+ if (!callback.is_null()) { |
+ // Provide any pending profiles to the callback immediately. |
+ std::vector<StackSamplingProfiler::Profile> profiles; |
+ GetProfiles(&profiles); |
+ if (!profiles.empty()) |
+ callback.Run(profiles); |
+ } |
+} |
+ |
+void DefaultProfileProcessor::ProcessProfiles( |
const std::vector<StackSamplingProfiler::Profile>& profiles) { |
- AutoLock scoped_lock(profiles_lock_); |
- profiles_.insert(profiles_.end(), profiles.begin(), profiles.end()); |
+ CompletedCallback callback = GetCompletedCallback(); |
+ |
+ // Store pending profiles if we don't have a valid callback. |
+ if (!callback.is_null()) { |
+ callback.Run(profiles); |
+ } else { |
+ AutoLock scoped_lock(profiles_lock_); |
+ profiles_.insert(profiles_.end(), profiles.begin(), profiles.end()); |
+ } |
} |
-void PendingProfiles::GetProfiles( |
+void DefaultProfileProcessor::GetProfiles( |
std::vector<StackSamplingProfiler::Profile>* profiles) { |
profiles->clear(); |
AutoLock scoped_lock(profiles_lock_); |
profiles_.swap(*profiles); |
} |
+ |
+DefaultProfileProcessor::CompletedCallback |
+DefaultProfileProcessor::GetCompletedCallback() const { |
+ AutoLock scoped_lock(callback_lock_); |
+ return default_completed_callback_; |
+} |
} // namespace |
StackSamplingProfiler::Module::Module() : base_address(nullptr) {} |
@@ -90,12 +135,11 @@ StackSamplingProfiler::Profile::~Profile() {} |
class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate { |
public: |
// Samples stacks using |native_sampler|. When complete, invokes |
- // |profiles_callback| with the collected profiles. |profiles_callback| must |
- // be thread-safe and may consume the contents of the vector. |
- SamplingThread( |
- scoped_ptr<NativeStackSampler> native_sampler, |
- const SamplingParams& params, |
- Callback<void(const std::vector<Profile>&)> completed_callback); |
+ // |completed_callback| with the collected profiles. |completed_callback| must |
+ // be thread-safe. |
+ SamplingThread(scoped_ptr<NativeStackSampler> native_sampler, |
+ const SamplingParams& params, |
+ CompletedCallback completed_callback); |
~SamplingThread() override; |
// Implementation of PlatformThread::Delegate: |
@@ -108,7 +152,7 @@ class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate { |
// collected, or false if collection was stopped before it completed. |
bool CollectProfile(Profile* profile, TimeDelta* elapsed_time); |
// Collects profiles from all bursts, or until the sampling is stopped. If |
- // stopped before complete, |profiles| will contains only full bursts. |
+ // stopped before complete, |profiles| will contain only full bursts. |
void CollectProfiles(std::vector<Profile>* profiles); |
scoped_ptr<NativeStackSampler> native_sampler_; |
@@ -117,7 +161,7 @@ class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate { |
WaitableEvent stop_event_; |
- Callback<void(const std::vector<Profile>&)> completed_callback_; |
+ CompletedCallback completed_callback_; |
DISALLOW_COPY_AND_ASSIGN(SamplingThread); |
}; |
@@ -125,7 +169,7 @@ class StackSamplingProfiler::SamplingThread : public PlatformThread::Delegate { |
StackSamplingProfiler::SamplingThread::SamplingThread( |
scoped_ptr<NativeStackSampler> native_sampler, |
const SamplingParams& params, |
- Callback<void(const std::vector<Profile>&)> completed_callback) |
+ CompletedCallback completed_callback) |
: native_sampler_(native_sampler.Pass()), |
params_(params), |
stop_event_(false, false), |
@@ -221,20 +265,26 @@ StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, |
const SamplingParams& params) |
: thread_id_(thread_id), params_(params) {} |
+StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id, |
+ const SamplingParams& params, |
+ CompletedCallback callback) |
+ : thread_id_(thread_id), params_(params), completed_callback_(callback) {} |
+ |
StackSamplingProfiler::~StackSamplingProfiler() {} |
void StackSamplingProfiler::Start() { |
- native_sampler_ = NativeStackSampler::Create(thread_id_); |
- if (!native_sampler_) |
+ scoped_ptr<NativeStackSampler> native_sampler( |
+ NativeStackSampler::Create(thread_id_)); |
+ if (!native_sampler) |
return; |
+ CompletedCallback callback = |
+ !completed_callback_.is_null() ? completed_callback_ : |
+ Bind(&DefaultProfileProcessor::ProcessProfiles, |
+ Unretained(DefaultProfileProcessor::GetInstance())); |
+ |
sampling_thread_.reset( |
- new SamplingThread( |
- native_sampler_.Pass(), params_, |
- (custom_completed_callback_.is_null() ? |
- Bind(&PendingProfiles::PutProfiles, |
- Unretained(PendingProfiles::GetInstance())) : |
- custom_completed_callback_))); |
+ new SamplingThread(native_sampler.Pass(), params_, callback)); |
if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get())) |
LOG(ERROR) << "failed to create thread"; |
} |
@@ -245,13 +295,9 @@ void StackSamplingProfiler::Stop() { |
} |
// static |
-void StackSamplingProfiler::GetPendingProfiles(std::vector<Profile>* profiles) { |
- PendingProfiles::GetInstance()->GetProfiles(profiles); |
-} |
- |
-void StackSamplingProfiler::SetCustomCompletedCallback( |
- Callback<void(const std::vector<Profile>&)> callback) { |
- custom_completed_callback_ = callback; |
+void StackSamplingProfiler::SetDefaultCompletedCallback( |
+ CompletedCallback callback) { |
+ DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback); |
} |
bool operator==(const StackSamplingProfiler::Frame &a, |