0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-09-26 18:38:52 +02:00

ircd: Split info::versions into header/unit.

This commit is contained in:
Jason Volk 2022-06-23 10:24:06 -07:00
parent 65d27f327e
commit d5c6314f1a
6 changed files with 192 additions and 164 deletions

View file

@ -19,8 +19,7 @@ extern "C" const char *const ircd_version;
/// Information & metadata about the library. /// Information & metadata about the library.
namespace ircd::info namespace ircd::info
{ {
struct line; using ircd::versions;
struct versions;
// Util // Util
void dump(); void dump();
@ -125,7 +124,7 @@ namespace ircd::info::hardware::x86
extern const bool sse, sse2, sse3, ssse3, sse4a, sse4_1, sse4_2; extern const bool sse, sse2, sse3, ssse3, sse4a, sse4_1, sse4_2;
extern const bool avx, avx2, avx512f; extern const bool avx, avx2, avx512f;
extern const bool tsc, tsc_constant; extern const bool tsc, tsc_constant;
}; }
namespace ircd::info::hardware::arm namespace ircd::info::hardware::arm
{ {
@ -137,81 +136,4 @@ namespace ircd::info::hardware::arm
extern const uint64_t ctr; extern const uint64_t ctr;
extern const string_view vendor; extern const string_view vendor;
};
/// Instances of `versions` create a dynamic version registry identifying
/// third-party dependencies throughout the project and its loaded modules.
///
/// Create a static instance of this class in a definition file or module
/// which has access to the version information of the dependency. Often there
/// can be two version identifiers for a dependency, one for headers and the
/// other for dynamically loaded shared object. In that case, create two
/// instances of this class with the same name.
///
struct ircd::info::versions
:instance_list<versions>
{
/// Our own name for the dependency.
string_view name;
/// Set the type to either API or ABI to indicate where this version
/// information has been sourced. Defaults to API.
enum type {API, ABI} type {API};
/// If the version number is a single (likely monotonic) integer.
long monotonic {0};
/// Alternative semantic version number.
std::array<long, 3> semantic {0};
/// Version string buffer. Copy any provided version string here.
char string[128] {0};
/// Convenience access to read the semantic version numbers.
auto &operator[](const int &idx) const;
/// Convenience access to read the monotonic integer; note that if zero
/// the semantic major number is read instead.
explicit operator const long &() const;
/// Convenience access to read the string
explicit operator string_view() const;
versions(const string_view &name,
const enum type &type = type::API,
const long &monotonic = 0,
const std::array<long, 3> &semantic = {0L},
const string_view &string = {});
versions(const string_view &name,
const enum type &type,
const long &monotonic,
const std::array<long, 3> &semantic,
const std::function<void (versions &, const mutable_buffer &)> &generator);
versions() = default;
versions(versions &&) = delete;
versions(const versions &) = delete;
~versions() noexcept;
};
inline ircd::info::versions::operator
const long &()
const
{
return monotonic?: semantic[0];
}
inline ircd::info::versions::operator
ircd::string_view()
const
{
return string;
}
inline auto &
ircd::info::versions::operator[](const int &idx)
const
{
return semantic.at(idx);
} }

View file

@ -57,6 +57,7 @@
#include "run.h" #include "run.h"
#include "demangle.h" #include "demangle.h"
#include "backtrace.h" #include "backtrace.h"
#include "versions.h"
#include "info.h" #include "info.h"
#include "logger.h" #include "logger.h"
#include "stringops.h" #include "stringops.h"

95
include/ircd/versions.h Normal file
View file

@ -0,0 +1,95 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2022 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_VERSIONS_H
namespace ircd
{
struct versions;
}
/// Instances of `versions` create a dynamic version registry identifying
/// third-party dependencies throughout the project and its loaded modules.
///
/// Create a static instance of this class in a definition file or module
/// which has access to the version information of the dependency. Often there
/// can be two version identifiers for a dependency, one for headers and the
/// other for dynamically loaded shared object. In that case, create two
/// instances of this class with the same name.
///
struct ircd::versions
:instance_list<versions>
{
/// Our own name for the dependency.
string_view name;
/// Set the type to either API or ABI to indicate where this version
/// information has been sourced. Defaults to API.
enum type {API, ABI} type {API};
/// If the version number is a single (likely monotonic) integer.
long monotonic {0};
/// Alternative semantic version number.
std::array<long, 3> semantic {0};
/// Version string buffer. Copy any provided version string here.
char string[128] {0};
/// Convenience access to read the semantic version numbers.
auto &operator[](const int &idx) const;
/// Convenience access to read the monotonic integer; note that if zero
/// the semantic major number is read instead.
explicit operator const long &() const;
/// Convenience access to read the string
explicit operator string_view() const;
versions(const string_view &name,
const enum type &type = type::API,
const long &monotonic = 0,
const std::array<long, 3> &semantic = {0L},
const string_view &string = {});
versions(const string_view &name,
const enum type &type,
const long &monotonic,
const std::array<long, 3> &semantic,
const std::function<void (versions &, const mutable_buffer &)> &generator);
versions() = default;
versions(versions &&) = delete;
versions(const versions &) = delete;
~versions() noexcept;
};
inline ircd::versions::operator
const long &()
const
{
return monotonic?: semantic[0];
}
inline ircd::versions::operator
ircd::string_view()
const
{
return string;
}
inline auto &
ircd::versions::operator[](const int &idx)
const
{
return semantic.at(idx);
}

View file

@ -160,6 +160,7 @@ libircd_la_SOURCES += simd.cc
libircd_la_SOURCES += fpe.cc libircd_la_SOURCES += fpe.cc
libircd_la_SOURCES += parse.cc libircd_la_SOURCES += parse.cc
libircd_la_SOURCES += lex_cast.cc libircd_la_SOURCES += lex_cast.cc
libircd_la_SOURCES += versions.cc
libircd_la_SOURCES += info.cc libircd_la_SOURCES += info.cc
libircd_la_SOURCES += allocator.cc libircd_la_SOURCES += allocator.cc
libircd_la_SOURCES += allocator_gnu.cc libircd_la_SOURCES += allocator_gnu.cc

View file

@ -52,90 +52,6 @@ ircd::info::dump()
fpe::debug_info(); fpe::debug_info();
} }
//
// Version registry
//
template<>
decltype(ircd::util::instance_list<ircd::info::versions>::allocator)
ircd::util::instance_list<ircd::info::versions>::allocator
{};
template<>
decltype(ircd::util::instance_list<ircd::info::versions>::list)
ircd::util::instance_list<ircd::info::versions>::list
{
allocator
};
/// Straightforward construction of versions members; string is copied
/// into member buffer with null termination.
ircd::info::versions::versions(const string_view &name,
const enum type &type,
const long &monotonic,
const std::array<long, 3> &semantic,
const string_view &string)
:versions
{
name, type, monotonic, semantic, [&string]
(auto &that, const mutable_buffer &buf)
{
strlcpy(buf, string);
}
}
{
}
/// Construction of versions members with closure for custom string generation.
/// The version string must be stored into buffer with null termination.
ircd::info::versions::versions(const string_view &name,
const enum type &type,
const long &monotonic,
const std::array<long, 3> &semantic,
const std::function<void (versions &, const mutable_buffer &)> &closure)
:name{name}
,type{type}
,monotonic{monotonic}
,semantic{semantic}
,string{'\0'}
{
if(closure) try
{
closure(*this, this->string);
}
catch(const std::exception &e)
{
log::error
{
"Querying %s version of '%s' :%s",
type == type::ABI? "ABI"_sv : "API"_sv,
name,
e.what(),
};
}
// User provided a string already; nothing else to do
if(strnlen(this->string, sizeof(this->string)) != 0)
return;
// Generate a string from the semantic version number or if all zeroes
// from the monotonic version number instead.
if(!this->semantic[0] && !this->semantic[1] && !this->semantic[2])
::snprintf(this->string, sizeof(this->string), "%ld",
this->monotonic);
else
::snprintf(this->string, sizeof(this->string), "%ld.%ld.%ld",
this->semantic[0],
this->semantic[1],
this->semantic[2]);
}
// Required for instance_list template instantiation.
ircd::info::versions::~versions()
noexcept
{
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Hardware / Platform // Hardware / Platform

93
ircd/versions.cc Normal file
View file

@ -0,0 +1,93 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2022 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
//
// Version registry
//
template<>
decltype(ircd::util::instance_list<ircd::versions>::allocator)
ircd::util::instance_list<ircd::versions>::allocator
{};
template<>
decltype(ircd::util::instance_list<ircd::versions>::list)
ircd::util::instance_list<ircd::versions>::list
{
allocator
};
/// Straightforward construction of versions members; string is copied
/// into member buffer with null termination.
ircd::versions::versions(const string_view &name,
const enum type &type,
const long &monotonic,
const std::array<long, 3> &semantic,
const string_view &string)
:versions
{
name, type, monotonic, semantic, [&string]
(auto &that, const mutable_buffer &buf)
{
strlcpy(buf, string);
}
}
{
}
/// Construction of versions members with closure for custom string generation.
/// The version string must be stored into buffer with null termination.
ircd::versions::versions(const string_view &name,
const enum type &type,
const long &monotonic,
const std::array<long, 3> &semantic,
const std::function<void (versions &, const mutable_buffer &)> &closure)
:name{name}
,type{type}
,monotonic{monotonic}
,semantic{semantic}
,string{'\0'}
{
if(closure) try
{
closure(*this, this->string);
}
catch(const std::exception &e)
{
log::error
{
"Querying %s version of '%s' :%s",
type == type::ABI? "ABI"_sv : "API"_sv,
name,
e.what(),
};
}
// User provided a string already; nothing else to do
if(strnlen(this->string, sizeof(this->string)) != 0)
return;
// Generate a string from the semantic version number or if all zeroes
// from the monotonic version number instead.
if(!this->semantic[0] && !this->semantic[1] && !this->semantic[2])
::snprintf(this->string, sizeof(this->string), "%ld",
this->monotonic);
else
::snprintf(this->string, sizeof(this->string), "%ld.%ld.%ld",
this->semantic[0],
this->semantic[1],
this->semantic[2]);
}
// Required for instance_list template instantiation.
ircd::versions::~versions()
noexcept
{
}