diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-13 02:51:07 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-13 02:51:07 +0000 |
commit | 19467c0bcc964f2af7e3ea07b08dad2cd46048bb (patch) | |
tree | 47c0544d79d351fd6bd259974826cf640170d98e /base/linux_util.cc | |
parent | 4f9bd8b843b94d9f3d5228084a94dad7286fa9c5 (diff) | |
download | chromium_src-19467c0bcc964f2af7e3ea07b08dad2cd46048bb.zip chromium_src-19467c0bcc964f2af7e3ea07b08dad2cd46048bb.tar.gz chromium_src-19467c0bcc964f2af7e3ea07b08dad2cd46048bb.tar.bz2 |
Make GetLinuxDistro thread-safe.
BUG=24659
TEST=none
Review URL: http://codereview.chromium.org/273026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28785 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/linux_util.cc')
-rw-r--r-- | base/linux_util.cc | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/base/linux_util.cc b/base/linux_util.cc index 7bdab94..40ca627 100644 --- a/base/linux_util.cc +++ b/base/linux_util.cc @@ -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,7 +46,50 @@ class EnvironmentVariableGetterImpl } }; -} // 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 { @@ -73,8 +118,12 @@ uint8_t* BGRAToRGBA(const uint8_t* pixels, int width, int height, int stride) { 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 @@ std::string GetLinuxDistro() { 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 |