| Index: base/profiler/stack_sampling_profiler.cc
|
| diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
|
| index 317400b2d4d70422b34f1abe7af1f4975e046522..1c08234fdf39ae05d5ff0d6326e49effb92cab01 100644
|
| --- a/base/profiler/stack_sampling_profiler.cc
|
| +++ b/base/profiler/stack_sampling_profiler.cc
|
| @@ -15,61 +15,102 @@
|
|
|
| namespace base {
|
|
|
| -// PendingProfiles ------------------------------------------------------------
|
| +// DefaultProfileProcessor ----------------------------------------------------
|
|
|
| namespace {
|
|
|
| -// Thread-safe singleton class that stores collected call stack 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();
|
| + using CompletedCallback = StackSamplingProfiler::CompletedCallback;
|
|
|
| - static PendingProfiles* GetInstance();
|
| + ~DefaultProfileProcessor();
|
|
|
| - // Appends |profiles| to |profiles_|. This function may be called on any
|
| - // thread.
|
| - void AppendProfiles(
|
| - const std::vector<StackSamplingProfiler::CallStackProfile>& 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 StackSamplingProfiler::CallStackProfiles& profiles);
|
| +
|
| + private:
|
| + friend struct DefaultSingletonTraits<DefaultProfileProcessor>;
|
| +
|
| + DefaultProfileProcessor();
|
|
|
| // Copies the pending profiles from |profiles_| into |profiles|, and clears
|
| // |profiles_|. This function may be called on any thread.
|
| void GetAndClearPendingProfiles(
|
| - std::vector<StackSamplingProfiler::CallStackProfile>* profiles);
|
| + StackSamplingProfiler::CallStackProfiles* profiles);
|
|
|
| - private:
|
| - friend struct DefaultSingletonTraits<PendingProfiles>;
|
| + // Gets the current completed callback, with proper locking.
|
| + CompletedCallback GetCompletedCallback() const;
|
|
|
| - PendingProfiles();
|
| + mutable Lock callback_lock_;
|
| + CompletedCallback default_completed_callback_;
|
|
|
| Lock profiles_lock_;
|
| - std::vector<StackSamplingProfiler::CallStackProfile> profiles_;
|
| + StackSamplingProfiler::CallStackProfiles profiles_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(PendingProfiles);
|
| + DISALLOW_COPY_AND_ASSIGN(DefaultProfileProcessor);
|
| };
|
|
|
| -PendingProfiles::PendingProfiles() {}
|
| -
|
| -PendingProfiles::~PendingProfiles() {}
|
| +DefaultProfileProcessor::~DefaultProfileProcessor() {}
|
|
|
| // static
|
| -PendingProfiles* PendingProfiles::GetInstance() {
|
| - return Singleton<PendingProfiles>::get();
|
| +DefaultProfileProcessor* DefaultProfileProcessor::GetInstance() {
|
| + return Singleton<DefaultProfileProcessor>::get();
|
| }
|
|
|
| -void PendingProfiles::AppendProfiles(
|
| - const std::vector<StackSamplingProfiler::CallStackProfile>& profiles) {
|
| - AutoLock scoped_lock(profiles_lock_);
|
| - profiles_.insert(profiles_.end(), profiles.begin(), profiles.end());
|
| +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.
|
| + StackSamplingProfiler::CallStackProfiles profiles;
|
| + GetAndClearPendingProfiles(&profiles);
|
| + if (!profiles.empty())
|
| + callback.Run(profiles);
|
| + }
|
| +}
|
| +
|
| +void DefaultProfileProcessor::ProcessProfiles(
|
| + const StackSamplingProfiler::CallStackProfiles& profiles) {
|
| + 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::GetAndClearPendingProfiles(
|
| - std::vector<StackSamplingProfiler::CallStackProfile>* profiles) {
|
| +DefaultProfileProcessor::DefaultProfileProcessor() {}
|
| +
|
| +void DefaultProfileProcessor::GetAndClearPendingProfiles(
|
| + StackSamplingProfiler::CallStackProfiles* 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
|
|
|
| @@ -209,7 +250,16 @@ StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
|
| const SamplingParams& params)
|
| : thread_id_(thread_id), params_(params) {}
|
|
|
| -StackSamplingProfiler::~StackSamplingProfiler() {}
|
| +StackSamplingProfiler::StackSamplingProfiler(PlatformThreadId thread_id,
|
| + const SamplingParams& params,
|
| + CompletedCallback callback)
|
| + : thread_id_(thread_id), params_(params), completed_callback_(callback) {}
|
| +
|
| +StackSamplingProfiler::~StackSamplingProfiler() {
|
| + Stop();
|
| + if (!sampling_thread_handle_.is_null())
|
| + PlatformThread::Join(sampling_thread_handle_);
|
| +}
|
|
|
| void StackSamplingProfiler::Start() {
|
| scoped_ptr<NativeStackSampler> native_sampler =
|
| @@ -217,14 +267,14 @@ void StackSamplingProfiler::Start() {
|
| 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::AppendProfiles,
|
| - Unretained(PendingProfiles::GetInstance())) :
|
| - custom_completed_callback_)));
|
| - if (!PlatformThread::CreateNonJoinable(0, sampling_thread_.get()))
|
| + new SamplingThread(native_sampler.Pass(), params_, callback));
|
| + if (!PlatformThread::Create(0, sampling_thread_.get(),
|
| + &sampling_thread_handle_))
|
| sampling_thread_.reset();
|
| }
|
|
|
| @@ -234,8 +284,9 @@ void StackSamplingProfiler::Stop() {
|
| }
|
|
|
| // static
|
| -void StackSamplingProfiler::GetPendingProfiles(CallStackProfiles* profiles) {
|
| - PendingProfiles::GetInstance()->GetAndClearPendingProfiles(profiles);
|
| +void StackSamplingProfiler::SetDefaultCompletedCallback(
|
| + CompletedCallback callback) {
|
| + DefaultProfileProcessor::GetInstance()->SetCompletedCallback(callback);
|
| }
|
|
|
| // StackSamplingProfiler::Frame global functions ------------------------------
|
|
|