Skip to content
Snippets Groups Projects

[LinuxVersion] Use "Construct on first use" idiom and add mutex

2 files
+ 24
12
Compare changes
  • Side-by-side
  • Inline
Files
2
+ 22
10
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2021 Florian Fischer
// Copyright © 2021-2022 Florian Fischer, Florian Schmaus
#include "lib/LinuxVersion.hpp"
#include <sys/utsname.h>
#include <cerrno>
#include <cstdlib>
#include <mutex>
#include "Common.hpp"
@@ -35,19 +36,30 @@ static auto checked_strtol(const std::string& s) -> long {
namespace emper::lib {
std::string LinuxVersion::globalVersion;
LinuxVersion::LinuxVersion() {
if (globalVersion.empty()) {
struct utsname buf;
if (uname(&buf)) {
DIE_MSG_ERRNO("Failed to invoke uname()");
auto LinuxVersion::getUtsRelease() -> const std::string& {
// Use "construct (members) on first use idiom" to prevent the "static initialization order
// fiasco/problem".
static std::string utsRelease;
// This mutex will become necessary once we call getUtsRelease(),
// and by implication LinuxVersion's constructor, concurrently. So
// it can not hurt to have it right now.
static std::mutex utsReleaseMutex;
{
const std::lock_guard<std::mutex> lock(utsReleaseMutex);
if (utsRelease.empty()) {
struct utsname buf;
if (uname(&buf)) {
DIE_MSG_ERRNO("Failed to invoke uname()");
}
utsRelease = std::string(buf.release);
}
globalVersion = std::string(buf.release);
}
version = globalVersion;
return utsRelease;
}
LinuxVersion::LinuxVersion() { version = getUtsRelease(); }
// Returns 1 if s is smaller, -1 if this is smaller, 0 if equal
auto LinuxVersion::compare(const std::string& s) -> int {
size_t dot_pos, dot_pos2;
Loading