From 6e8314767440c90f9cf1a351e35bdf752abec056 Mon Sep 17 00:00:00 2001 From: Pedro Maciel Date: Mon, 21 Aug 2023 12:20:00 +0100 Subject: [PATCH] eckit::geometry instance()-based factories (7/7) --- src/eckit/geometry/Grid.cc | 167 +++------------------------ src/eckit/geometry/Grid.h | 77 +++--------- src/eckit/geometry/GridConfig.cc | 23 +++- src/eckit/geometry/grid/HEALPix.cc | 2 +- src/eckit/geometry/grid/ReducedGG.cc | 4 +- src/eckit/geometry/grid/RegularGG.cc | 2 +- src/eckit/geometry/grid/RegularLL.cc | 2 +- src/tools/eckit-grid-list.cc | 3 +- src/tools/eckit-grid.cc | 5 +- tests/geometry/test_grid.cc | 3 +- 10 files changed, 60 insertions(+), 228 deletions(-) diff --git a/src/eckit/geometry/Grid.cc b/src/eckit/geometry/Grid.cc index b19110528..465420242 100644 --- a/src/eckit/geometry/Grid.cc +++ b/src/eckit/geometry/Grid.cc @@ -14,12 +14,9 @@ #include #include -#include -#include "eckit/config/MappedConfiguration.h" #include "eckit/exception/Exceptions.h" #include "eckit/geometry/GridConfig.h" -#include "eckit/geometry/util/regex.h" #include "eckit/log/Log.h" #include "eckit/thread/AutoLock.h" #include "eckit/thread/Mutex.h" @@ -94,31 +91,25 @@ Renumber Grid::reorder(const PointLonLat&) const { } -static pthread_once_t __once; - -static Mutex* __mutex = nullptr; -static std::map* __grid_uids = nullptr; -static std::map* __grid_names = nullptr; - -static void __init() { - __mutex = new Mutex; - __grid_uids = new std::remove_reference::type; - __grid_names = new std::remove_reference::type; +GridFactory& GridFactory::instance() { + static GridFactory obj; + return obj; } -const Grid* GridFactory::build(const Configuration& config) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); +const Grid* GridFactory::build_(const Configuration& config) const { + AutoLock lock(mutex_); GridConfig::instance(); if (std::string uid; config.get("uid", uid)) { - return GridFactoryUID::build(uid); + std::unique_ptr cfg(GridConfigurationUID::instance().get(uid).config()); + return build(*cfg); } if (std::string name; config.get("name", name)) { - return GridFactoryName::build(name); + std::unique_ptr cfg(GridConfigurationName::instance().match(name).config(name)); + return build(*cfg); } if (std::string type; config.get("type", type)) { @@ -130,147 +121,15 @@ const Grid* GridFactory::build(const Configuration& config) { } -void GridFactory::list(std::ostream& out) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); +void GridFactory::list_(std::ostream& out) const { + AutoLock lock(mutex_); GridConfig::instance(); - GridFactoryUID::list(out << "uid: "); - out << std::endl; - - GridFactoryName::list(out << "name: "); - out << std::endl; - + out << GridConfigurationUID::instance() << std::endl; + out << GridConfigurationName::instance() << std::endl; out << GridFactoryType::instance() << std::endl; } -GridFactoryUID::GridFactoryUID(const std::string& uid) : - uid_(uid) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - if (__grid_uids->find(uid) == __grid_uids->end()) { - (*__grid_uids)[uid] = this; - return; - } - - throw SeriousBug("Grid: duplicate identifier '" + uid + "'"); -} - - -GridFactoryUID::~GridFactoryUID() { - AutoLock lock(*__mutex); - __grid_uids->erase(uid_); -} - - -const Grid* GridFactoryUID::build(const std::string& uid) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - if (auto j = __grid_uids->find(uid); j != __grid_uids->end()) { - std::unique_ptr config(j->second->config()); - return GridFactory::build(*config); - } - - list(Log::error() << "Grid: unknown identifier '" << uid << "', choices are: "); - throw SeriousBug("Grid: unknown identifier '" + uid + "'"); -} - - -void GridFactoryUID::list(std::ostream& out) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - out << "..." << std::endl; -} - - -void GridFactoryUID::insert(const std::string& uid, MappedConfiguration* config) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - struct Insert final : GridFactoryUID { - Insert(const std::string& uid, MappedConfiguration* config) : - GridFactoryUID(uid), config_(config) {} - Configuration* config() override { return new MappedConfiguration(*config_); } - const std::unique_ptr config_; - }; - - new Insert(uid, config); -} - - -GridFactoryName::GridFactoryName(const std::string& pattern, const std::string& example) : - pattern_(pattern), example_(example) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - if (__grid_names->find(pattern) == __grid_names->end()) { - (*__grid_names)[pattern] = this; - return; - } - - throw SeriousBug("Grid: duplicate name '" + pattern + "'"); -} - - -const Grid* GridFactoryName::build(const std::string& name) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - const auto end = __grid_names->cend(); - - auto i = end; - for (auto j = __grid_names->cbegin(); j != end; ++j) { - if (util::regex_match(j->second->pattern_, name)) { - if (i != end) { - throw SeriousBug("Grid: name '" + name + "' matches '" + i->second->pattern_ + "' and '" + j->second->pattern_ + "'"); - } - i = j; - } - } - - if (i != end) { - std::unique_ptr config(i->second->config(name)); - return GridFactory::build(*config); - } - - list(Log::error() << "Grid: unknown name '" << name << "', choices are: "); - throw SeriousBug("Grid: unknown name '" + name + "'"); -} - - -void GridFactoryName::list(std::ostream& out) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - out << "..." << std::endl; -} - - -void GridFactoryName::insert(const std::string& name, MappedConfiguration* config) { - pthread_once(&__once, __init); - AutoLock lock(*__mutex); - - struct Insert final : GridFactoryName { - Insert(const std::string& name, const std::string& example, MappedConfiguration* config) : - GridFactoryName(name, example), config_(config) {} - Configuration* config(const std::string&) const override { return new MappedConfiguration(*config_); } - const std::unique_ptr config_; - }; - - ASSERT(config != nullptr); - new Insert(name, config->getString("example", ""), config); -} - - -GridFactoryName::~GridFactoryName() { - AutoLock lock(*__mutex); - __grid_names->erase(pattern_); -} - - } // namespace eckit::geometry diff --git a/src/eckit/geometry/Grid.h b/src/eckit/geometry/Grid.h index 7e35cb8a1..84f2627e6 100644 --- a/src/eckit/geometry/Grid.h +++ b/src/eckit/geometry/Grid.h @@ -21,6 +21,7 @@ #include "eckit/config/MappedConfiguration.h" #include "eckit/geometry/Area.h" +#include "eckit/geometry/Configurator.h" #include "eckit/geometry/Increments.h" #include "eckit/geometry/Iterator.h" #include "eckit/geometry/Ordering.h" @@ -168,80 +169,34 @@ class Grid { }; -using GridFactoryType = Factory; +using GridFactoryType = Factory; +using GridConfigurationName = Configurator>; +using GridConfigurationUID = Configurator; + template using GridRegisterType = ConcreteBuilderT1; +template +using GridRegisterUID = ConcreteConfigurationGeneratorT0; -struct GridFactory { - // This is 'const' as Grid should always be immutable - static const Grid* build(const Configuration&); - static void list(std::ostream&); -}; - +template +using GridRegisterName = ConcreteConfigurationGeneratorT1; -struct GridFactoryUID { - GridFactoryUID(const GridFactoryUID&) = delete; - GridFactoryUID(GridFactoryUID&&) = delete; - GridFactoryUID& operator=(const GridFactoryUID&) = delete; - GridFactoryUID& operator=(GridFactoryUID&&) = delete; +struct GridFactory { // This is 'const' as Grid should always be immutable - static const Grid* build(const std::string&); - - static void list(std::ostream&); - static void insert(const std::string& name, MappedConfiguration*); - -protected: - explicit GridFactoryUID(const std::string& uid); - virtual ~GridFactoryUID(); + static const Grid* build(const Configuration& config) { return instance().build_(config); } + static void list(std::ostream& out) { return instance().list_(out); } private: - virtual Configuration* config() = 0; - - const std::string uid_; -}; - - -struct GridFactoryName { - GridFactoryName(const GridFactoryName&) = delete; - GridFactoryName(GridFactoryName&&) = delete; - GridFactoryName& operator=(const GridFactoryName&) = delete; - GridFactoryName& operator=(GridFactoryName&&) = delete; + static GridFactory& instance(); // This is 'const' as Grid should always be immutable - static const Grid* build(const std::string& name); - - static void list(std::ostream&); - static void insert(const std::string& name, MappedConfiguration*); - -protected: - explicit GridFactoryName(const std::string& pattern, const std::string& example = ""); - virtual ~GridFactoryName(); - -private: - Configuration* config() const { return config(example_); } - virtual Configuration* config(const std::string& name) const = 0; - - const std::string pattern_; - const std::string example_; -}; - - -template -struct GridRegisterUID final : GridFactoryUID { - explicit GridRegisterUID(const std::string& uid) : - GridFactoryUID(uid) {} - Configuration* config() override { return T::config(); } -}; - + const Grid* build_(const Configuration&) const; + void list_(std::ostream&) const; -template -struct GridRegisterName final : GridFactoryName { - explicit GridRegisterName(const std::string& pattern, const std::string& example) : - GridFactoryName(pattern, example) {} - Configuration* config(const std::string& name) const override { return T::config(name); } + mutable Mutex mutex_; }; diff --git a/src/eckit/geometry/GridConfig.cc b/src/eckit/geometry/GridConfig.cc index e2ec18223..70363ca63 100644 --- a/src/eckit/geometry/GridConfig.cc +++ b/src/eckit/geometry/GridConfig.cc @@ -13,6 +13,7 @@ #include "eckit/geometry/GridConfig.h" #include +#include #include "eckit/config/MappedConfiguration.h" #include "eckit/exception/Exceptions.h" @@ -76,24 +77,38 @@ GridConfig::GridConfig(const PathName& path) { auto* config = new MappedConfiguration; config_.reset(config); + struct ConfigurationFromUID final : GridConfigurationUID::configurator_t { + explicit ConfigurationFromUID(MappedConfiguration* config) : + config_(config) {} + Configuration* config() const override { return new MappedConfiguration(*config_); } + std::unique_ptr config_; + }; + + struct ConfigurationFromName final : GridConfigurationName::configurator_t { + explicit ConfigurationFromName(MappedConfiguration* config) : + config_(config) {} + Configuration* config(GridConfigurationName::configurator_t::arg1_t) const override { return new MappedConfiguration(*config_); } + std::unique_ptr config_; + }; + if (path.exists()) { ValueMap map(YAMLParser::decodeFile(path)); for (const auto& kv : map) { const auto key = kv.first.as(); - if (key == "grid_names") { + if (key == "grid_uids") { for (ValueMap m : static_cast(kv.second)) { ASSERT(m.size() == 1); - GridFactoryName::insert(m.begin()->first, config_from_value_map(m.begin()->second)); + GridConfigurationUID::instance().regist(m.begin()->first.as(), new ConfigurationFromUID(config_from_value_map(m.begin()->second))); } continue; } - if (key == "grid_uids") { + if (key == "grid_names") { for (ValueMap m : static_cast(kv.second)) { ASSERT(m.size() == 1); - GridFactoryUID::insert(m.begin()->first, config_from_value_map(m.begin()->second)); + GridConfigurationName::instance().regist(m.begin()->first.as(), new ConfigurationFromName(config_from_value_map(m.begin()->second))); } continue; } diff --git a/src/eckit/geometry/grid/HEALPix.cc b/src/eckit/geometry/grid/HEALPix.cc index 4393a32f8..f021d8153 100644 --- a/src/eckit/geometry/grid/HEALPix.cc +++ b/src/eckit/geometry/grid/HEALPix.cc @@ -218,7 +218,7 @@ std::pair, std::vector> HEALPix::to_latlon() const { static const GridRegisterType __grid_type("healpix"); -static const GridRegisterName __grid_pattern("[hH][1-9][0-9]*", "H2"); +static const GridRegisterName __grid_pattern("[hH][1-9][0-9]*"); } // namespace eckit::geometry::grid diff --git a/src/eckit/geometry/grid/ReducedGG.cc b/src/eckit/geometry/grid/ReducedGG.cc index b365ec42c..e49225481 100644 --- a/src/eckit/geometry/grid/ReducedGG.cc +++ b/src/eckit/geometry/grid/ReducedGG.cc @@ -187,8 +187,8 @@ struct ReducedGGOctahedral { static const GridRegisterType __grid_type("reduced_gg"); -static const GridRegisterName __grid_pattern_1("[nN][1-9][0-9]*", "N16"); -static const GridRegisterName __grid_pattern_2("[oO][1-9][0-9]*", "O2"); +static const GridRegisterName __grid_pattern_1("[nN][1-9][0-9]*"); +static const GridRegisterName __grid_pattern_2("[oO][1-9][0-9]*"); } // namespace eckit::geometry::grid diff --git a/src/eckit/geometry/grid/RegularGG.cc b/src/eckit/geometry/grid/RegularGG.cc index 6645f123d..d456e145d 100644 --- a/src/eckit/geometry/grid/RegularGG.cc +++ b/src/eckit/geometry/grid/RegularGG.cc @@ -182,7 +182,7 @@ Iterator* RegularGG::iterator() const { static const GridRegisterType __grid_type("regular_gg"); -static const GridRegisterName __grid_pattern("[fF][1-9][0-9]*", "F2"); +static const GridRegisterName __grid_pattern("[fF][1-9][0-9]*"); } // namespace eckit::geometry::grid diff --git a/src/eckit/geometry/grid/RegularLL.cc b/src/eckit/geometry/grid/RegularLL.cc index 12ee11c01..1ccf67024 100644 --- a/src/eckit/geometry/grid/RegularLL.cc +++ b/src/eckit/geometry/grid/RegularLL.cc @@ -250,7 +250,7 @@ Configuration* RegularLL::config(const std::string& name) { } -static const GridRegisterName __grid_pattern(POSITIVE_REAL "/" POSITIVE_REAL, "30/45"); +static const GridRegisterName __grid_pattern(POSITIVE_REAL "/" POSITIVE_REAL); #undef POSITIVE_REAL diff --git a/src/tools/eckit-grid-list.cc b/src/tools/eckit-grid-list.cc index bd96224dc..149e0d1bd 100644 --- a/src/tools/eckit-grid-list.cc +++ b/src/tools/eckit-grid-list.cc @@ -22,7 +22,8 @@ struct EckitGridList final : EckitTool { EckitTool(argc, argv) {} void execute(const option::CmdArgs&) override { - Log::info() << geometry::GridFactoryType::instance() << std::endl; + geometry::GridFactory::list(Log::info()); + Log::info() << std::endl; } void usage(const std::string& tool) const override { diff --git a/src/tools/eckit-grid.cc b/src/tools/eckit-grid.cc index bdbbd50f9..998942595 100644 --- a/src/tools/eckit-grid.cc +++ b/src/tools/eckit-grid.cc @@ -11,7 +11,7 @@ #include #include -#include "eckit/config/Resource.h" +#include "eckit/config/MappedConfiguration.h" #include "eckit/exception/Exceptions.h" #include "eckit/geometry/Grid.h" #include "eckit/geometry/Point.h" @@ -52,7 +52,8 @@ class EckitGrid final : public EckitTool { out.precision(args.getInt("precision", 16)); for (const auto& arg : args) { - std::unique_ptr grid(uid ? geometry::GridFactoryUID::build(arg) : geometry::GridFactoryName::build(arg)); + std::unique_ptr cfg(new MappedConfiguration({{uid ? "uid" : "name", std::string(arg)}})); + std::unique_ptr grid(geometry::GridFactory::build(*cfg)); out << "size: " << grid->size() << std::endl; diff --git a/tests/geometry/test_grid.cc b/tests/geometry/test_grid.cc index e18dcafb9..f2280b577 100644 --- a/tests/geometry/test_grid.cc +++ b/tests/geometry/test_grid.cc @@ -32,7 +32,8 @@ CASE("GridFactory::build") { SECTION("GridFactory::build_from_name") { for (const auto& test : {test_t{"O2", 88}, {"f2", 32}, {"h2", 48}}) { - std::unique_ptr grid(geometry::GridFactoryName::build(test.name)); + std::unique_ptr cfg(new MappedConfiguration({{"name", test.name}})); + std::unique_ptr grid(geometry::GridFactory::build(*cfg)); auto size = grid->size(); EXPECT_EQUAL(size, test.size); }