Skip to content

Commit

Permalink
eckit::geometry instance()-based factories (7/7)
Browse files Browse the repository at this point in the history
  • Loading branch information
pmaciel committed Aug 21, 2023
1 parent 20898d2 commit 6e83147
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 228 deletions.
167 changes: 13 additions & 154 deletions src/eckit/geometry/Grid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,9 @@

#include <memory>
#include <ostream>
#include <type_traits>

#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"
Expand Down Expand Up @@ -94,31 +91,25 @@ Renumber Grid::reorder(const PointLonLat&) const {
}


static pthread_once_t __once;

static Mutex* __mutex = nullptr;
static std::map<std::string, GridFactoryUID*>* __grid_uids = nullptr;
static std::map<std::string, GridFactoryName*>* __grid_names = nullptr;

static void __init() {
__mutex = new Mutex;
__grid_uids = new std::remove_reference<decltype(*__grid_uids)>::type;
__grid_names = new std::remove_reference<decltype(*__grid_names)>::type;
GridFactory& GridFactory::instance() {
static GridFactory obj;
return obj;
}


const Grid* GridFactory::build(const Configuration& config) {
pthread_once(&__once, __init);
AutoLock<Mutex> lock(*__mutex);
const Grid* GridFactory::build_(const Configuration& config) const {
AutoLock<Mutex> lock(mutex_);

GridConfig::instance();

if (std::string uid; config.get("uid", uid)) {
return GridFactoryUID::build(uid);
std::unique_ptr<Configuration> cfg(GridConfigurationUID::instance().get(uid).config());
return build(*cfg);
}

if (std::string name; config.get("name", name)) {
return GridFactoryName::build(name);
std::unique_ptr<Configuration> cfg(GridConfigurationName::instance().match(name).config(name));
return build(*cfg);
}

if (std::string type; config.get("type", type)) {
Expand All @@ -130,147 +121,15 @@ const Grid* GridFactory::build(const Configuration& config) {
}


void GridFactory::list(std::ostream& out) {
pthread_once(&__once, __init);
AutoLock<Mutex> lock(*__mutex);
void GridFactory::list_(std::ostream& out) const {
AutoLock<Mutex> 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<Mutex> lock(*__mutex);

if (__grid_uids->find(uid) == __grid_uids->end()) {
(*__grid_uids)[uid] = this;
return;
}

throw SeriousBug("Grid: duplicate identifier '" + uid + "'");
}


GridFactoryUID::~GridFactoryUID() {
AutoLock<Mutex> lock(*__mutex);
__grid_uids->erase(uid_);
}


const Grid* GridFactoryUID::build(const std::string& uid) {
pthread_once(&__once, __init);
AutoLock<Mutex> lock(*__mutex);

if (auto j = __grid_uids->find(uid); j != __grid_uids->end()) {
std::unique_ptr<Configuration> 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<Mutex> lock(*__mutex);

out << "..." << std::endl;
}


void GridFactoryUID::insert(const std::string& uid, MappedConfiguration* config) {
pthread_once(&__once, __init);
AutoLock<Mutex> 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<MappedConfiguration> config_;
};

new Insert(uid, config);
}


GridFactoryName::GridFactoryName(const std::string& pattern, const std::string& example) :
pattern_(pattern), example_(example) {
pthread_once(&__once, __init);
AutoLock<Mutex> 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<Mutex> 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<Configuration> 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<Mutex> lock(*__mutex);

out << "..." << std::endl;
}


void GridFactoryName::insert(const std::string& name, MappedConfiguration* config) {
pthread_once(&__once, __init);
AutoLock<Mutex> 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<MappedConfiguration> config_;
};

ASSERT(config != nullptr);
new Insert(name, config->getString("example", ""), config);
}


GridFactoryName::~GridFactoryName() {
AutoLock<Mutex> lock(*__mutex);
__grid_names->erase(pattern_);
}


} // namespace eckit::geometry
77 changes: 16 additions & 61 deletions src/eckit/geometry/Grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -168,80 +169,34 @@ class Grid {
};


using GridFactoryType = Factory<Grid>;
using GridFactoryType = Factory<Grid>;
using GridConfigurationName = Configurator<ConfigurationGeneratorT1<const std::string&>>;
using GridConfigurationUID = Configurator<ConfigurationGeneratorT0>;


template <typename T>
using GridRegisterType = ConcreteBuilderT1<Grid, T>;

template <typename T>
using GridRegisterUID = ConcreteConfigurationGeneratorT0<T>;

struct GridFactory {
// This is 'const' as Grid should always be immutable
static const Grid* build(const Configuration&);
static void list(std::ostream&);
};

template <typename T>
using GridRegisterName = ConcreteConfigurationGeneratorT1<T, const std::string&>;

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 <class T>
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 <class T>
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_;
};


Expand Down
23 changes: 19 additions & 4 deletions src/eckit/geometry/GridConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "eckit/geometry/GridConfig.h"

#include <algorithm>
#include <memory>

#include "eckit/config/MappedConfiguration.h"
#include "eckit/exception/Exceptions.h"
Expand Down Expand Up @@ -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<MappedConfiguration> 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<MappedConfiguration> config_;
};

if (path.exists()) {
ValueMap map(YAMLParser::decodeFile(path));

for (const auto& kv : map) {
const auto key = kv.first.as<std::string>();

if (key == "grid_names") {
if (key == "grid_uids") {
for (ValueMap m : static_cast<ValueList>(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<std::string>(), new ConfigurationFromUID(config_from_value_map(m.begin()->second)));
}
continue;
}

if (key == "grid_uids") {
if (key == "grid_names") {
for (ValueMap m : static_cast<ValueList>(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<std::string>(), new ConfigurationFromName(config_from_value_map(m.begin()->second)));
}
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/eckit/geometry/grid/HEALPix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ std::pair<std::vector<double>, std::vector<double>> HEALPix::to_latlon() const {


static const GridRegisterType<HEALPix> __grid_type("healpix");
static const GridRegisterName<HEALPix> __grid_pattern("[hH][1-9][0-9]*", "H2");
static const GridRegisterName<HEALPix> __grid_pattern("[hH][1-9][0-9]*");


} // namespace eckit::geometry::grid
4 changes: 2 additions & 2 deletions src/eckit/geometry/grid/ReducedGG.cc
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ struct ReducedGGOctahedral {


static const GridRegisterType<ReducedGG> __grid_type("reduced_gg");
static const GridRegisterName<ReducedGGClassical> __grid_pattern_1("[nN][1-9][0-9]*", "N16");
static const GridRegisterName<ReducedGGOctahedral> __grid_pattern_2("[oO][1-9][0-9]*", "O2");
static const GridRegisterName<ReducedGGClassical> __grid_pattern_1("[nN][1-9][0-9]*");
static const GridRegisterName<ReducedGGOctahedral> __grid_pattern_2("[oO][1-9][0-9]*");


} // namespace eckit::geometry::grid
2 changes: 1 addition & 1 deletion src/eckit/geometry/grid/RegularGG.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ Iterator* RegularGG::iterator() const {


static const GridRegisterType<RegularGG> __grid_type("regular_gg");
static const GridRegisterName<RegularGG> __grid_pattern("[fF][1-9][0-9]*", "F2");
static const GridRegisterName<RegularGG> __grid_pattern("[fF][1-9][0-9]*");


} // namespace eckit::geometry::grid
2 changes: 1 addition & 1 deletion src/eckit/geometry/grid/RegularLL.cc
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ Configuration* RegularLL::config(const std::string& name) {
}


static const GridRegisterName<RegularLL> __grid_pattern(POSITIVE_REAL "/" POSITIVE_REAL, "30/45");
static const GridRegisterName<RegularLL> __grid_pattern(POSITIVE_REAL "/" POSITIVE_REAL);


#undef POSITIVE_REAL
Expand Down
Loading

0 comments on commit 6e83147

Please sign in to comment.