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
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2021 Florian Fischer
// Copyright © 2021-2022 Florian Fischer, Florian Schmaus
#include "lib/LinuxVersion.hpp"
#include "lib/LinuxVersion.hpp"
#include <sys/utsname.h>
#include <sys/utsname.h>
#include <cerrno>
#include <cerrno>
#include <cstdlib>
#include <cstdlib>
 
#include <mutex>
#include "Common.hpp"
#include "Common.hpp"
@@ -35,19 +36,30 @@ static auto checked_strtol(const std::string& s) -> long {
@@ -35,19 +36,30 @@ static auto checked_strtol(const std::string& s) -> long {
namespace emper::lib {
namespace emper::lib {
std::string LinuxVersion::globalVersion;
auto LinuxVersion::getUtsRelease() -> const std::string& {
// Use "construct (members) on first use idiom" to prevent the "static initialization order
LinuxVersion::LinuxVersion() {
// fiasco/problem".
if (globalVersion.empty()) {
static std::string utsRelease;
struct utsname buf;
// This mutex will become necessary once we call getUtsRelease(),
if (uname(&buf)) {
// and by implication LinuxVersion's constructor, concurrently. So
DIE_MSG_ERRNO("Failed to invoke uname()");
// 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
// Returns 1 if s is smaller, -1 if this is smaller, 0 if equal
auto LinuxVersion::compare(const std::string& s) -> int {
auto LinuxVersion::compare(const std::string& s) -> int {
size_t dot_pos, dot_pos2;
size_t dot_pos, dot_pos2;
Loading