Skip to content

Commit

Permalink
Fix initialization and thread-safety of SDF::Version() global (#1522)
Browse files Browse the repository at this point in the history
Replace a static global variable that used a pre-main constructor with
a latch-initialized static local variable and mutex to guard the writes.

This does not change API but it does change ABI.

Signed-off-by: Jeremy Nimmer <[email protected]>
  • Loading branch information
jwnimmer-tri authored Jan 6, 2025
1 parent aaadeea commit 5d9623e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
6 changes: 2 additions & 4 deletions include/sdf/SDFImpl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ namespace sdf
public: const std::string &OriginalVersion() const;

/// \brief Get the version
/// The result will be set to SDF_VERSION by default, unless overridden by a
/// call to the Version(const std::string &) function at runtime.
/// \return The version as a string
public: static std::string Version();

Expand Down Expand Up @@ -290,10 +292,6 @@ namespace sdf
/// \internal
/// \brief Pointer to private data.
private: std::unique_ptr<SDFPrivate> dataPtr;

/// \brief The SDF version. Set to SDF_VERSION by default, or through
/// the Version function at runtime.
private: static std::string version;
};
/// \}
}
Expand Down
28 changes: 22 additions & 6 deletions src/SDF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
#include <functional>
#include <list>
#include <map>
#include <mutex>
#include <string>
#include <vector>

#include <gz/utils/NeverDestroyed.hh>

#include "sdf/parser.hh"
#include "sdf/Assert.hh"
#include "sdf/Console.hh"
Expand All @@ -42,10 +45,6 @@ namespace sdf
{
inline namespace SDF_VERSION_NAMESPACE
{
// TODO(azeey) This violates the Google style guide. Change to a function that
// returns the version string when possible.
std::string SDF::version = SDF_VERSION; // NOLINT(runtime/string)

std::string sdfSharePath()
{
std::string sharePath = sdf::getSharePath();
Expand Down Expand Up @@ -488,16 +487,33 @@ const std::string &SDF::OriginalVersion() const
return this->dataPtr->originalVersion;
}

/////////////////////////////////////////////////
namespace {
// Infrastructe to support the SDF::Version(...) static getter and setter.
struct GlobalVersion {
std::mutex mutex;
std::string version{SDF_VERSION};
};
GlobalVersion& GetMutableGlobalVersionSingleton() {
static gz::utils::NeverDestroyed<GlobalVersion> singleton;
return singleton.Access();
}
} // namespace

/////////////////////////////////////////////////
std::string SDF::Version()
{
return version;
GlobalVersion& singleton = GetMutableGlobalVersionSingleton();
std::lock_guard guard{singleton.mutex};
return std::string{singleton.version};
}

/////////////////////////////////////////////////
void SDF::Version(const std::string &_version)
{
version = _version;
GlobalVersion& singleton = GetMutableGlobalVersionSingleton();
std::lock_guard guard{singleton.mutex};
singleton.version = _version;
}

/////////////////////////////////////////////////
Expand Down

0 comments on commit 5d9623e

Please sign in to comment.