blob: 49d04bc3c5807ed10952271cc81ccb44dea27be8 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_WMI_REFRESHER_H_
#define CHROME_BROWSER_PERFORMANCE_MONITOR_WMI_REFRESHER_H_
#include <wrl/client.h>
#include <atomic>
#include "base/base_export.h"
#include "base/callback.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/system/system_monitor.h"
#include "base/win/wmi.h"
namespace performance_monitor {
namespace win {
// Wrapper around an IWbemRefresher instance used to retrieve some system
// performance counters.
//
// The constructor and InitializeDiskIdleTimeConfig() don't have any sequencing
// requirements. Calls to RefreshAndGetDiskIdleTimeInPercent() must happen on
// the same sequence, after InitializeDiskIdleTimeConfig() has returned. All
// methods except the constructor must be invoked in a context that accepts
// blocking calls (e.g. a MayBlock() sequence).
//
// This class relies on the fact that by default all sequences are in a
// multithreaded COM apartment.
class WMIRefresher {
public:
WMIRefresher();
~WMIRefresher();
// Initialize everything needed to retrieve the disk idle time data via WMI.
// This should only be called once.
//
// Returns true on success, false otherwise.
bool InitializeDiskIdleTimeConfig();
// Refresh the disk idle time data from WMI. This cannot be called until the
// call to InitializeDiskIdleTimeConfig has completed.
//
// Returns the disk idle time in percent if available (between 0.0 and 100.0),
// base::nullopt otherwise.
base::Optional<float> RefreshAndGetDiskIdleTimeInPercent();
private:
enum class InitStatus;
enum class RefreshStatus;
// Implementation of |Start|.
void InitializeDiskIdleTimeConfigImpl(InitStatus* res);
// Implementation of |Refresh|.
base::Optional<float> RefreshAndGetDiskIdleTimeInPercentImpl(
RefreshStatus* res);
// The WMI service instance.
Microsoft::WRL::ComPtr<IWbemServices> wmi_services_;
// The refresher responsible for collecting some local performance data via
// WMI. |wmi_refresher_->Refresh()| should be called at regular intervals to
// refresh the data.
Microsoft::WRL::ComPtr<IWbemRefresher> wmi_refresher_;
// The WMI enumerator.
Microsoft::WRL::ComPtr<IWbemHiPerfEnum> wmi_refresher_enum_;
// The latest number of objects returned by the refresher, initialized to 2 as
// it's the minimal number of objects returned by the refresher (one for the
// "Total" value and one per hard drive).
size_t wmi_refresher_enum_objects_latest_count_ = 2;
// The handle to the properties that need to be read in |Refresh|.
base::Optional<long> percent_idle_time_prop_handle_;
base::Optional<long> percent_idle_time_base_prop_handle_;
// Latest values that have been read in |Refresh|.
base::Optional<DWORD> latest_percent_idle_time_val_;
base::Optional<DWORD> latest_percent_idle_time_base_val_;
// Indicates if |InitializeDiskIdleTimeConfig| has already been called.
std::atomic<bool> initialized_called_;
// Indicates if everything is properly initialized and if this object is
// ready to be used.
bool refresh_ready_ = false;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(WMIRefresher);
};
} // namespace win
} // namespace performance_monitor
#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_WMI_REFRESHER_H_