| 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,
|
|
|