From 503b9c5bbfe0c9e07247629d8a45a1c1e62c34ca Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 25 Mar 2021 12:16:15 +0000 Subject: [PATCH] Move proj_transform_cache declarations and implementaion into separate translation unit (ref VC++ C2492) --- .../mapnik/feature_style_processor_impl.hpp | 6 +- include/mapnik/map.hpp | 36 +-------- include/mapnik/proj_transform_cache.hpp | 76 +++++++++++++++++++ src/build.py | 1 + src/map.cpp | 43 +++-------- src/proj_transform_cache.cpp | 58 ++++++++++++++ .../unit/renderer/feature_style_processor.cpp | 1 - 7 files changed, 154 insertions(+), 67 deletions(-) create mode 100644 include/mapnik/proj_transform_cache.hpp create mode 100644 src/proj_transform_cache.cpp diff --git a/include/mapnik/feature_style_processor_impl.hpp b/include/mapnik/feature_style_processor_impl.hpp index d85c3235d..96c4da3d1 100644 --- a/include/mapnik/feature_style_processor_impl.hpp +++ b/include/mapnik/feature_style_processor_impl.hpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -254,7 +254,7 @@ void feature_style_processor::prepare_layer(layer_rendering_material } processor_context_ptr current_ctx = ds->get_context(ctx_map); - proj_transform * proj_trans_ptr = m_.get_proj_transform(mat.proj0_.params(), mat.proj1_.params()); + proj_transform const* proj_trans_ptr = m_.get_proj_transform(mat.proj0_.params(), mat.proj1_.params()); box2d query_ext = extent; // unbuffered box2d buffered_query_ext(query_ext); // buffered @@ -493,7 +493,7 @@ void feature_style_processor::render_material(layer_rendering_materia layer const& lay = mat.lay_; std::vector const & rule_caches = mat.rule_caches_; - proj_transform * proj_trans_ptr = m_.get_proj_transform(mat.proj0_.params(), mat.proj1_.params()); + proj_transform const* proj_trans_ptr = m_.get_proj_transform(mat.proj0_.params(), mat.proj1_.params()); bool cache_features = lay.cache_features() && active_styles.size() > 1; datasource_ptr ds = lay.datasource(); diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index af60147ec..7b0c155c5 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -38,9 +38,6 @@ MAPNIK_DISABLE_WARNING_PUSH #include #include -#include -#include -#include MAPNIK_DISABLE_WARNING_POP // stl @@ -56,36 +53,11 @@ using featureset_ptr = std::shared_ptr; class feature_type_style; class view_transform; class layer; +struct proj_transform_cache; class MAPNIK_DECL Map : boost::equality_comparable { public: - using key_type = std::pair; - using compatible_key_type = std::pair; - - struct compatible_hash - { - template - std::size_t operator() (KeyType const& key) const - { - using hash_type = boost::hash; - std::size_t seed = hash_type{}(key.first); - seed ^= hash_type{}(key.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - return seed; - } - }; - - struct compatible_predicate - { - bool operator()(compatible_key_type const& k1, - compatible_key_type const& k2) const - { - return k1 == k2; - } - }; - - using proj_cache_type = boost::unordered_map, compatible_hash>; - enum aspect_fix_mode { // grow the width or height of the specified geo bbox to fill the map size. default behaviour. @@ -131,9 +103,8 @@ private: boost::optional font_directory_; freetype_engine::font_file_mapping_type font_file_mapping_; freetype_engine::font_memory_cache_type font_memory_cache_; - thread_local static proj_cache_type proj_cache_; + std::unique_ptr proj_cache_ = {}; public: - using const_style_iterator = std::map::const_iterator; using style_iterator = std::map::iterator; using const_fontset_iterator = std::map::const_iterator; @@ -530,7 +501,8 @@ public: return font_memory_cache_; } - proj_transform * get_proj_transform(std::string const& source, std::string const& dest) const; + proj_transform const* get_proj_transform(std::string const& source, std::string const& dest) const; + private: friend void swap(Map & rhs, Map & lhs); void fixAspectRatio(); diff --git a/include/mapnik/proj_transform_cache.hpp b/include/mapnik/proj_transform_cache.hpp new file mode 100644 index 000000000..b080081aa --- /dev/null +++ b/include/mapnik/proj_transform_cache.hpp @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2021 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + + +#ifndef MAPNIK_PROJ_TRANSFORM_CACHE_HPP +#define MAPNIK_PROJ_TRANSFORM_CACHE_HPP + +#include +#include + +MAPNIK_DISABLE_WARNING_PUSH +#include +#include +#include +#include +MAPNIK_DISABLE_WARNING_POP + +namespace mapnik { + +struct proj_transform_cache : util::noncopyable +{ + using key_type = std::pair; + using compatible_key_type = std::pair; + + struct compatible_hash + { + template + std::size_t operator() (KeyType const& key) const + { + using hash_type = boost::hash; + std::size_t seed = hash_type{}(key.first); + seed ^= hash_type{}(key.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } + }; + + struct compatible_predicate + { + bool operator()(compatible_key_type const& k1, + compatible_key_type const& k2) const + { + return k1 == k2; + } + }; + + using cache_type = boost::unordered_map, compatible_hash>; + + proj_transform_cache() = default; + + thread_local static cache_type cache_; + void init(std::string const& source, std::string const& dest) const; + proj_transform const* get(std::string const& source, std::string const& dest) const; +}; + +} + +#endif // MAPNIK_PROJ_TRANSFORM_CACHE_HPP diff --git a/src/build.py b/src/build.py index 171fb941e..9227c1089 100644 --- a/src/build.py +++ b/src/build.py @@ -214,6 +214,7 @@ source = Split( twkb.cpp projection.cpp proj_transform.cpp + proj_transform_cache.cpp scale_denominator.cpp simplify.cpp parse_transform.cpp diff --git a/src/map.cpp b/src/map.cpp index 5763f1474..8d20225ca 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -63,8 +63,9 @@ static const char * aspect_fix_mode_strings[] = { IMPLEMENT_ENUM( aspect_fix_mode_e, aspect_fix_mode_strings ) + Map::Map() -: width_(400), +: width_(400), height_(400), srs_(MAPNIK_GEOGRAPHIC_PROJ), buffer_size_(0), @@ -136,11 +137,11 @@ Map::Map(Map && rhs) extra_params_(std::move(rhs.extra_params_)), font_directory_(std::move(rhs.font_directory_)), font_file_mapping_(std::move(rhs.font_file_mapping_)), - font_memory_cache_(std::move(rhs.font_memory_cache_)) {} + font_memory_cache_(std::move(rhs.font_memory_cache_)), + proj_cache_(std::move(rhs.proj_cache_)) {} Map::~Map() {} -thread_local Map::proj_cache_type Map::proj_cache_ = proj_cache_type(); Map& Map::operator=(Map rhs) { @@ -327,21 +328,6 @@ size_t Map::layer_count() const return layers_.size(); } -proj_transform * Map::get_proj_transform(std::string const& source, std::string const& dest) const -{ - - compatible_key_type key = std::make_pair(source, dest); - auto itr = proj_cache_.find(key, compatible_hash{}, compatible_predicate{}); - if (itr == proj_cache_.end()) - { - mapnik::projection srs1(source, true); - mapnik::projection srs2(dest, true); - return proj_cache_.emplace(std::make_pair(source, dest), - std::make_unique(srs1, srs2)).first->second.get(); - } - return itr->second.get(); -} - void Map::add_layer(layer const& l) { init_proj_transform(srs_, l.srs()); @@ -366,7 +352,6 @@ void Map::remove_all() fontsets_.clear(); font_file_mapping_.clear(); font_memory_cache_.clear(); - proj_cache_.clear(); } layer const& Map::get_layer(size_t index) const @@ -551,7 +536,7 @@ void Map::zoom_all() if (layer.active()) { std::string const& layer_srs = layer.srs(); - proj_transform * proj_trans_ptr = get_proj_transform(srs_, layer_srs);; + proj_transform const* proj_trans_ptr = proj_cache_->get(srs_, layer_srs);; box2d layer_ext = layer.envelope(); if (proj_trans_ptr->backward(layer_ext, PROJ_ENVELOPE_POINTS)) { @@ -731,7 +716,7 @@ featureset_ptr Map::query_point(unsigned index, double x, double y) const mapnik::datasource_ptr ds = layer.datasource(); if (ds) { - proj_transform * proj_trans_ptr = get_proj_transform(layer.srs(), srs_); + proj_transform const* proj_trans_ptr = proj_cache_->get(layer.srs(), srs_); double z = 0; if (!proj_trans_ptr->equal() && !proj_trans_ptr->backward(x,y,z)) { @@ -794,18 +779,14 @@ void Map::set_extra_parameters(parameters& params) extra_params_ = params; } +mapnik::proj_transform const* Map::get_proj_transform(std::string const& source, std::string const& dest) const +{ + return proj_cache_->get(source, dest); +} void Map::init_proj_transform(std::string const& source, std::string const& dest) { - compatible_key_type key = std::make_pair(source, dest); - auto itr = proj_cache_.find(key, compatible_hash{}, compatible_predicate{}); - if (itr == proj_cache_.end()) - { - mapnik::projection p0(source, true); - mapnik::projection p1(dest, true); - proj_cache_.emplace(std::make_pair(source, dest), - std::make_unique(p0, p1)); - } + proj_cache_->init(source, dest); } void Map::init_proj_transforms() diff --git a/src/proj_transform_cache.cpp b/src/proj_transform_cache.cpp new file mode 100644 index 000000000..1e051bd8a --- /dev/null +++ b/src/proj_transform_cache.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2021 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include + +namespace mapnik { + +thread_local proj_transform_cache::cache_type proj_transform_cache::cache_ = cache_type(); + +void proj_transform_cache::init(std::string const& source, std::string const& dest) const +{ + compatible_key_type key = std::make_pair(source, dest); + auto itr = cache_.find(key, compatible_hash{}, compatible_predicate{}); + if (itr == cache_.end()) + { + mapnik::projection p0(source, true); + mapnik::projection p1(dest, true); + cache_.emplace(std::make_pair(source, dest), + std::make_unique(p0, p1)); + } +} + +proj_transform const* proj_transform_cache::get(std::string const& source, std::string const& dest) const +{ + + compatible_key_type key = std::make_pair(source, dest); + auto itr = cache_.find(key, compatible_hash{}, compatible_predicate{}); + if (itr == cache_.end()) + { + mapnik::projection srs1(source, true); + mapnik::projection srs2(dest, true); + return cache_.emplace(std::make_pair(source, dest), + std::make_unique(srs1, srs2)).first->second.get(); + } + return itr->second.get(); +} + + +} // namespace mapnik diff --git a/test/unit/renderer/feature_style_processor.cpp b/test/unit/renderer/feature_style_processor.cpp index ed125bf52..28d87ec22 100644 --- a/test/unit/renderer/feature_style_processor.cpp +++ b/test/unit/renderer/feature_style_processor.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include