| Index: base/linux_util.cc
|
| ===================================================================
|
| --- base/linux_util.cc (revision 28738)
|
| +++ base/linux_util.cc (working copy)
|
| @@ -9,7 +9,9 @@
|
| #include <vector>
|
|
|
| #include "base/command_line.h"
|
| +#include "base/lock.h"
|
| #include "base/process_util.h"
|
| +#include "base/singleton.h"
|
| #include "base/string_util.h"
|
|
|
| namespace {
|
| @@ -44,8 +46,51 @@
|
| }
|
| };
|
|
|
| -} // anonymous namespace
|
| +enum LinuxDistroState {
|
| + STATE_DID_NOT_CHECK = 0,
|
| + STATE_CHECK_STARTED = 1,
|
| + STATE_CHECK_FINISHED = 2,
|
| +};
|
|
|
| +// Helper class for GetLinuxDistro().
|
| +class LinuxDistroHelper {
|
| + public:
|
| + // Retrieves the Singleton.
|
| + static LinuxDistroHelper* Get() {
|
| + return Singleton<LinuxDistroHelper>::get();
|
| + }
|
| +
|
| + // The simple state machine goes from:
|
| + // STATE_DID_NOT_CHECK -> STATE_CHECK_STARTED -> STATE_CHECK_FINISHED.
|
| + LinuxDistroHelper() : state_(STATE_DID_NOT_CHECK) {}
|
| + ~LinuxDistroHelper() {}
|
| +
|
| + // Retrieve the current state, if we're in STATE_DID_NOT_CHECK,
|
| + // we automatically move to STATE_CHECK_STARTED so nobody else will
|
| + // do the check.
|
| + LinuxDistroState State() {
|
| + AutoLock scoped_lock(lock_);
|
| + if (STATE_DID_NOT_CHECK == state_) {
|
| + state_ = STATE_CHECK_STARTED;
|
| + return STATE_DID_NOT_CHECK;
|
| + }
|
| + return state_;
|
| + }
|
| +
|
| + // Indicate the check finished, move to STATE_CHECK_FINISHED.
|
| + void CheckFinished() {
|
| + AutoLock scoped_lock(lock_);
|
| + DCHECK(state_ == STATE_CHECK_STARTED);
|
| + state_ = STATE_CHECK_FINISHED;
|
| + }
|
| +
|
| + private:
|
| + Lock lock_;
|
| + LinuxDistroState state_;
|
| +};
|
| +
|
| +} // anonymous namespace
|
| +
|
| namespace base {
|
|
|
| uint8_t* BGRAToRGBA(const uint8_t* pixels, int width, int height, int stride) {
|
| @@ -73,8 +118,12 @@
|
| std::string linux_distro = "Unknown";
|
|
|
| std::string GetLinuxDistro() {
|
| - static bool checked_distro = false;
|
| - if (!checked_distro) {
|
| + LinuxDistroHelper* distro_state_singleton = LinuxDistroHelper::Get();
|
| + LinuxDistroState state = distro_state_singleton->State();
|
| + if (STATE_DID_NOT_CHECK == state) {
|
| + // We do this check only once per process. If it fails, there's
|
| + // little reason to believe it will work if we attempt to run
|
| + // lsb_release again.
|
| std::vector<std::string> argv;
|
| argv.push_back("lsb_release");
|
| argv.push_back("-d");
|
| @@ -86,12 +135,16 @@
|
| if (output.compare(0, field.length(), field) == 0)
|
| linux_distro = output.substr(field.length());
|
| }
|
| - // We do this check only once per process. If it fails, there's
|
| - // little reason to believe it will work if we attempt to run
|
| - // lsb_release again.
|
| - checked_distro = true;
|
| + distro_state_singleton->CheckFinished();
|
| + return linux_distro;
|
| + } else if (STATE_CHECK_STARTED == state) {
|
| + // If the distro check above is in progress in some other thread, we're
|
| + // not going to wait for the results.
|
| + return "Unknown";
|
| + } else {
|
| + // In STATE_CHECK_FINISHED, no more writing to |linux_distro|.
|
| + return linux_distro;
|
| }
|
| - return linux_distro;
|
| }
|
|
|
| // static
|
|
|