From 6025585f01393c772a9a0d9574c09400cd036d0c Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Mon, 18 Jul 2022 20:13:33 -0600 Subject: [PATCH] switch from std::any to class hierarchy for content_stats_t Fixes bogus (huge integers) content stats reporting on macOS (also fix tjunc stats reporting) having the non-copyable std::atomic inside a std::any which must be copyable was problematic IMO this is slightly better because it lets us use non-copyable types --- common/bspfile.cc | 34 ++++++++++++++-------------------- include/common/bspfile.hh | 10 +++++++--- qbsp/brush.cc | 10 +++++----- qbsp/brushbsp.cc | 4 ++-- qbsp/tjunc.cc | 2 +- 5 files changed, 29 insertions(+), 31 deletions(-) diff --git a/common/bspfile.cc b/common/bspfile.cc index a7756996..98db9226 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -559,7 +559,7 @@ public: } private: - struct content_stats_t + struct content_stats_t : public content_stats_base_t { std::atomic solid; std::atomic empty; @@ -569,20 +569,17 @@ private: std::atomic detail_fence; std::atomic sky; std::atomic illusionary_visblocker; - - content_stats_t() = default; - inline content_stats_t(const content_stats_t ©) { } }; public: - std::any create_content_stats() const override + std::unique_ptr create_content_stats() const override { - return content_stats_t{}; + return std::unique_ptr(new content_stats_t{}); } - void count_contents_in_stats(const contentflags_t &contents, std::any &stats_any) const override + void count_contents_in_stats(const contentflags_t &contents, content_stats_base_t &stats_any) const override { - content_stats_t &stats = std::any_cast(stats_any); + content_stats_t &stats = dynamic_cast(stats_any); if (contents_are_solid(contents)) { stats.solid++; @@ -603,9 +600,9 @@ public: } } - void print_content_stats(const std::any &stats_any, const char *what) const override + void print_content_stats(const content_stats_base_t &stats_any, const char *what) const override { - const content_stats_t &stats = std::any_cast(stats_any); + const content_stats_t &stats = dynamic_cast(stats_any); if (stats.empty) { logging::print(logging::flag::STAT, " {:8} empty {}\n", stats.empty, what); @@ -1281,26 +1278,23 @@ public: } private: - struct content_stats_t + struct content_stats_t : public content_stats_base_t { //std::array, 32> native_types; std::unordered_map native_types; std::atomic total_brushes; std::atomic visblocker_brushes; - - content_stats_t() = default; - inline content_stats_t(const content_stats_t ©) { } }; public: - std::any create_content_stats() const override + std::unique_ptr create_content_stats() const override { - return content_stats_t{}; + return std::unique_ptr(new content_stats_t{}); } - void count_contents_in_stats(const contentflags_t &contents, std::any &stats_any) const override + void count_contents_in_stats(const contentflags_t &contents, content_stats_base_t &stats_any) const override { - content_stats_t &stats = std::any_cast(stats_any); + content_stats_t &stats = dynamic_cast(stats_any); /*for (int32_t i = 0; i < 32; i++) { if (contents.native & nth_bit(i)) { @@ -1320,9 +1314,9 @@ public: stats.total_brushes++; } - void print_content_stats(const std::any &stats_any, const char *what) const override + void print_content_stats(const content_stats_base_t &stats_any, const char *what) const override { - const content_stats_t &stats = std::any_cast(stats_any); + const content_stats_t &stats = dynamic_cast(stats_any); /*for (int32_t i = 0; i < 32; i++) { if (stats.native_types[i]) { diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index a6e84776..8b34b090 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -233,6 +233,10 @@ enum gameid_t GAME_TOTAL }; +struct content_stats_base_t { + virtual ~content_stats_base_t() = default; +}; + // Game definition, which contains data specific to // the game a BSP version is being compiled for. struct gamedef_t @@ -304,9 +308,9 @@ struct gamedef_t const std::string &texname, const surfflags_t &flags, const contentflags_t &contents) const = 0; virtual void init_filesystem(const fs::path &source, const settings::common_settings &settings) const = 0; virtual const std::vector &get_default_palette() const = 0; - virtual std::any create_content_stats() const = 0; - virtual void count_contents_in_stats(const contentflags_t &contents, std::any &stats) const = 0; - virtual void print_content_stats(const std::any &stats, const char *what) const = 0; + virtual std::unique_ptr create_content_stats() const = 0; + virtual void count_contents_in_stats(const contentflags_t &contents, content_stats_base_t &stats) const = 0; + virtual void print_content_stats(const content_stats_base_t &stats, const char *what) const = 0; }; // Lump specification; stores the name and size diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 1a8fad72..e2937e4b 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -841,7 +841,7 @@ std::optional LoadBrush(const mapentity_t *src, const mapbrush_t *ma //============================================================================= -static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum, std::any &stats) +static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum, content_stats_base_t &stats) { const mapbrush_t *mapbrush; qvec3d rotate_offset{}; @@ -1063,9 +1063,9 @@ hullnum 0 does not contain clip brushes. */ void Brush_LoadEntity(mapentity_t *entity, const int hullnum) { - std::any stats = qbsp_options.target_game->create_content_stats(); + auto stats = qbsp_options.target_game->create_content_stats(); - Brush_LoadEntity(entity, entity, hullnum, stats); + Brush_LoadEntity(entity, entity, hullnum, *stats); /* * If this is the world entity, find all func_group and func_detail @@ -1085,12 +1085,12 @@ void Brush_LoadEntity(mapentity_t *entity, const int hullnum) ProcessAreaPortal(source); if (IsWorldBrushEntity(source) || IsNonRemoveWorldBrushEntity(source)) { - Brush_LoadEntity(entity, source, hullnum, stats); + Brush_LoadEntity(entity, source, hullnum, *stats); } } } - qbsp_options.target_game->print_content_stats(stats, "brushes"); + qbsp_options.target_game->print_content_stats(*stats, "brushes"); } void bspbrush_t::update_bounds() diff --git a/qbsp/brushbsp.cc b/qbsp/brushbsp.cc index 0bfb2acb..a00c4be6 100644 --- a/qbsp/brushbsp.cc +++ b/qbsp/brushbsp.cc @@ -48,7 +48,7 @@ constexpr int PSIDE_BOTH = (PSIDE_FRONT|PSIDE_BACK); constexpr int PSIDE_FACING = 4; struct bspstats_t { - std::any leafstats; + std::unique_ptr leafstats; // total number of nodes, includes c_nonvis std::atomic c_nodes; // number of nodes created by splitting on a side_t which had !visible @@ -414,7 +414,7 @@ static void LeafNode(node_t *leafnode, std::vector> leafnode->original_brushes.push_back(brush->original); } - qbsp_options.target_game->count_contents_in_stats(leafnode->contents, stats.leafstats); + qbsp_options.target_game->count_contents_in_stats(leafnode->contents, *stats.leafstats); } //============================================================ diff --git a/qbsp/tjunc.cc b/qbsp/tjunc.cc index 1b1a3bbd..bb2cef84 100644 --- a/qbsp/tjunc.cc +++ b/qbsp/tjunc.cc @@ -636,7 +636,7 @@ void TJunc(node_t *headnode) { logging::print(logging::flag::PROGRESS, "---- {} ----\n", __func__); - tjunc_stats_t stats; + tjunc_stats_t stats{}; std::unordered_set faces; FindFaces_r(headnode, faces);