From e5bc4b32214f42cd5d25f5e6480a6f5d16bc65fc Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 28 May 2023 02:50:39 -0400 Subject: [PATCH 1/7] Add identity for std::mutex --- library/include/DataIdentity.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/include/DataIdentity.h b/library/include/DataIdentity.h index fd47429b9..c5ce0fb73 100644 --- a/library/include/DataIdentity.h +++ b/library/include/DataIdentity.h @@ -25,10 +25,11 @@ distribution. #pragma once #include -#include +#include +#include #include +#include #include -#include #include "DataDefs.h" @@ -570,6 +571,11 @@ namespace df static opaque_identity *get() { return &identity; } }; + template<> struct DFHACK_EXPORT identity_traits { + static opaque_identity identity; + static opaque_identity *get() { return &identity; } + }; + template<> struct DFHACK_EXPORT identity_traits { static ptr_string_identity identity; static ptr_string_identity *get() { return &identity; } From 7c4d9364a25a1c2be8111221db08d4b3e691a6e5 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 28 May 2023 02:51:06 -0400 Subject: [PATCH 2/7] Make allocator_fn compile for non-copy-assignable types like std::mutex --- library/include/DataDefs.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 174156e76..7d840a9ad 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -497,11 +497,25 @@ namespace df using DFHack::DfLinkedList; using DFHack::DfOtherVectors; + template + typename std::enable_if< + std::is_copy_assignable::value + >::type allocator_try_assign(void *out, const void *in) { + *(T*)out = *(const T*)in; + } + + template + typename std::enable_if< + !std::is_copy_assignable::value + >::type allocator_try_assign(void *out, const void *in) { + // assignment is not possible; do nothing + } + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" template void *allocator_fn(void *out, const void *in) { - if (out) { *(T*)out = *(const T*)in; return out; } + if (out) { allocator_try_assign(out, in); return out; } else if (in) { delete (T*)in; return (T*)in; } else return new T(); } From 6fbb22e9127ae9e43e2346457167f43acf1712cf Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 28 May 2023 13:07:21 -0400 Subject: [PATCH 3/7] Add missing instantion for identity_traits, refactor code shared with fstream identity --- library/DataStaticsFields.cpp | 12 +++++------- library/include/DataDefs.h | 7 +++++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/library/DataStaticsFields.cpp b/library/DataStaticsFields.cpp index 8318b523d..ac2b415eb 100644 --- a/library/DataStaticsFields.cpp +++ b/library/DataStaticsFields.cpp @@ -17,6 +17,9 @@ namespace df { category##_identity identity_traits::identity(name); #define INTEGER_IDENTITY_TRAITS(type, name) NUMBER_IDENTITY_TRAITS(integer, type, name) #define FLOAT_IDENTITY_TRAITS(type) NUMBER_IDENTITY_TRAITS(float, type, #type) +#define OPAQUE_IDENTITY_TRAITS_NAME(type, name) \ + opaque_identity identity_traits::identity(sizeof(type), allocator_noassign_fn, name) +#define STL_OPAQUE_IDENTITY_TRAITS(type) OPAQUE_IDENTITY_TRAITS_NAME(std::type, #type) #ifndef STATIC_FIELDS_GROUP INTEGER_IDENTITY_TRAITS(char, "char"); @@ -42,13 +45,8 @@ namespace df { stl_bit_vector_identity identity_traits >::identity; bit_array_identity identity_traits >::identity; - static void *fstream_allocator_fn(void *out, const void *in) { - if (out) { /* *(T*)out = *(const T*)in;*/ return NULL; } - else if (in) { delete (std::fstream*)in; return (std::fstream*)in; } - else return new std::fstream(); - } - opaque_identity identity_traits::identity( - sizeof(std::fstream), fstream_allocator_fn, "fstream"); + STL_OPAQUE_IDENTITY_TRAITS(fstream); + STL_OPAQUE_IDENTITY_TRAITS(mutex); buffer_container_identity buffer_container_identity::base_instance; #endif diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 7d840a9ad..0109f0fd0 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -528,6 +528,13 @@ namespace df else return new T(); } + template + void *allocator_noassign_fn(void *out, const void *in) { + if (out) { return NULL; } + else if (in) { delete (T*)in; return (T*)in; } + else return new T(); + } + template struct identity_traits { static compound_identity *get() { return &T::_identity; } From d0250ae4261ad009167d12ec36b5d56a330f903a Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 28 May 2023 13:08:06 -0400 Subject: [PATCH 4/7] Update allocator_try_assign() to match behavior of fstream allocator for non-copyable types Looks like the choice we have made here previously is to return NULL if attempting to allocate types that we cannot allocate. --- library/include/DataDefs.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 0109f0fd0..e03e9a0a8 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -499,23 +499,27 @@ namespace df template typename std::enable_if< - std::is_copy_assignable::value + std::is_copy_assignable::value, + void* >::type allocator_try_assign(void *out, const void *in) { *(T*)out = *(const T*)in; + return out; } template typename std::enable_if< - !std::is_copy_assignable::value + !std::is_copy_assignable::value, + void* >::type allocator_try_assign(void *out, const void *in) { // assignment is not possible; do nothing + return NULL; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" template void *allocator_fn(void *out, const void *in) { - if (out) { allocator_try_assign(out, in); return out; } + if (out) { return allocator_try_assign(out, in); } else if (in) { delete (T*)in; return (T*)in; } else return new T(); } From eb12ff17f6fc71a8b7c78c91ad46959c2e640555 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 28 May 2023 13:21:49 -0400 Subject: [PATCH 5/7] Refactor: move static identity_traits to their own file, simplify field defs DataStaticsFields.cpp used to contain identity_traits specializations for primitive and opaque STL types, as well as macros used for the generated struct field definitions. Only one of these were actually used in any compilation unit, and the identity_traits definitions were hidden behind a guard to prevent them from being compiled at all when building the struct field definitions. Now, the identity_traits specializations live in their own file, DataIdentity.cpp (matching their declarations, which live in DataIdentity.h). This speeds up build times because modifying these specializations no longer requires rebuilding all of the field definitions unnecessarily. --- library/CMakeLists.txt | 11 +++++----- ...DataStaticsFields.cpp => DataIdentity.cpp} | 22 +++---------------- library/include/DataStaticsFields.inc | 15 +++++++++++++ library/modules/Screen.cpp | 3 +-- 4 files changed, 24 insertions(+), 27 deletions(-) rename library/{DataStaticsFields.cpp => DataIdentity.cpp} (74%) create mode 100644 library/include/DataStaticsFields.inc diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 8b1b7f65d..2ea2d830f 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -62,6 +62,7 @@ set(MAIN_SOURCES ColorText.cpp CompilerWorkAround.cpp DataDefs.cpp + DataIdentity.cpp Debug.cpp Error.cpp VTableInterpose.cpp @@ -71,7 +72,6 @@ set(MAIN_SOURCES LuaApi.cpp DataStatics.cpp DataStaticsCtor.cpp - DataStaticsFields.cpp MiscUtils.cpp Types.cpp PluginManager.cpp @@ -186,8 +186,7 @@ foreach(GROUP other a b c d e f g h i j k l m n o p q r s t u v w x y z) set(STATIC_FIELDS_INC_FILENAME "df/static.fields-${GROUP}.inc") endif() file(WRITE ${STATIC_FIELDS_FILENAME}.tmp - "#define STATIC_FIELDS_GROUP\n" - "#include \"../DataStaticsFields.cpp\"\n" + "#include \"DataStaticsFields.inc\"\n" "#include \"${STATIC_FIELDS_INC_FILENAME}\"\n" ) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different @@ -294,15 +293,15 @@ add_custom_target(generate_headers if(REMOVE_SYMBOLS_FROM_DF_STUBS) if(UNIX) # Don't produce debug info for generated stubs - set_source_files_properties(DataStatics.cpp DataStaticsCtor.cpp DataStaticsFields.cpp ${STATIC_FIELDS_FILES} + set_source_files_properties(DataStatics.cpp DataStaticsCtor.cpp ${STATIC_FIELDS_FILES} PROPERTIES COMPILE_FLAGS "-g0 -O1") else(WIN32) - set_source_files_properties(DataStatics.cpp DataStaticsCtor.cpp DataStaticsFields.cpp ${STATIC_FIELDS_FILES} + set_source_files_properties(DataStatics.cpp DataStaticsCtor.cpp ${STATIC_FIELDS_FILES} PROPERTIES COMPILE_FLAGS "/O1 /bigobj") endif() else() if(WIN32) - set_source_files_properties(DataStatics.cpp DataStaticsCtor.cpp DataStaticsFields.cpp ${STATIC_FIELDS_FILES} + set_source_files_properties(DataStatics.cpp DataStaticsCtor.cpp ${STATIC_FIELDS_FILES} PROPERTIES COMPILE_FLAGS "/Od /bigobj") endif() endif() diff --git a/library/DataStaticsFields.cpp b/library/DataIdentity.cpp similarity index 74% rename from library/DataStaticsFields.cpp rename to library/DataIdentity.cpp index ac2b415eb..f6a1c2de8 100644 --- a/library/DataStaticsFields.cpp +++ b/library/DataIdentity.cpp @@ -1,17 +1,12 @@ #include #include - -#ifndef STATIC_FIELDS_GROUP -#include "DataDefs.h" -#endif +#include +#include +#include #include "DataFuncs.h" -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Winvalid-offsetof" -#endif - namespace df { #define NUMBER_IDENTITY_TRAITS(category, type, name) \ category##_identity identity_traits::identity(name); @@ -50,15 +45,4 @@ namespace df { buffer_container_identity buffer_container_identity::base_instance; #endif -#undef NUMBER_IDENTITY_TRAITS -#undef INTEGER_IDENTITY_TRAITS -#undef FLOAT_IDENTITY_TRAITS } - -#define TID(type) (&identity_traits< type >::identity) - -#define FLD(mode, name) struct_field_info::mode, #name, offsetof(CUR_STRUCT, name) -#define GFLD(mode, name) struct_field_info::mode, #name, (size_t)&df::global::name -#define METHOD(mode, name) struct_field_info::mode, #name, 0, wrap_function(&CUR_STRUCT::name) -#define METHOD_N(mode, func, name) struct_field_info::mode, #name, 0, wrap_function(&CUR_STRUCT::func) -#define FLD_END struct_field_info::END diff --git a/library/include/DataStaticsFields.inc b/library/include/DataStaticsFields.inc new file mode 100644 index 000000000..97a036b58 --- /dev/null +++ b/library/include/DataStaticsFields.inc @@ -0,0 +1,15 @@ +#include + +#include "DataFuncs.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + +#define TID(type) (&identity_traits< type >::identity) + +#define FLD(mode, name) struct_field_info::mode, #name, offsetof(CUR_STRUCT, name) +#define GFLD(mode, name) struct_field_info::mode, #name, (size_t)&df::global::name +#define METHOD(mode, name) struct_field_info::mode, #name, 0, wrap_function(&CUR_STRUCT::name) +#define METHOD_N(mode, func, name) struct_field_info::mode, #name, 0, wrap_function(&CUR_STRUCT::func) +#define FLD_END struct_field_info::END diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index c7ef88c60..2ee91a089 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -1092,8 +1092,7 @@ df::plant *dfhack_lua_viewscreen::getSelectedPlant() return Lua::GetDFObject(Lua::Core::State, -1); } -#define STATIC_FIELDS_GROUP -#include "../DataStaticsFields.cpp" +#include "DataStaticsFields.inc" using df::identity_traits; From 2f427451758e6d3467e94da8dd3f202dfbe36e5e Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 29 May 2023 01:09:59 -0400 Subject: [PATCH 6/7] Add identity_traits, add macro for opaque identities --- library/DataIdentity.cpp | 1 + library/include/DataIdentity.h | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/library/DataIdentity.cpp b/library/DataIdentity.cpp index f6a1c2de8..0f85e5d95 100644 --- a/library/DataIdentity.cpp +++ b/library/DataIdentity.cpp @@ -40,6 +40,7 @@ namespace df { stl_bit_vector_identity identity_traits >::identity; bit_array_identity identity_traits >::identity; + STL_OPAQUE_IDENTITY_TRAITS(condition_variable); STL_OPAQUE_IDENTITY_TRAITS(fstream); STL_OPAQUE_IDENTITY_TRAITS(mutex); diff --git a/library/include/DataIdentity.h b/library/include/DataIdentity.h index c5ce0fb73..232b32108 100644 --- a/library/include/DataIdentity.h +++ b/library/include/DataIdentity.h @@ -24,6 +24,7 @@ distribution. #pragma once +#include #include #include #include @@ -542,6 +543,12 @@ namespace df #define INTEGER_IDENTITY_TRAITS(type) NUMBER_IDENTITY_TRAITS(integer, type) #define FLOAT_IDENTITY_TRAITS(type) NUMBER_IDENTITY_TRAITS(float, type) +#define OPAQUE_IDENTITY_TRAITS(type) \ + template<> struct DFHACK_EXPORT identity_traits { \ + static opaque_identity identity; \ + static opaque_identity *get() { return &identity; } \ + }; + INTEGER_IDENTITY_TRAITS(char); INTEGER_IDENTITY_TRAITS(signed char); INTEGER_IDENTITY_TRAITS(unsigned char); @@ -555,6 +562,9 @@ namespace df INTEGER_IDENTITY_TRAITS(unsigned long long); FLOAT_IDENTITY_TRAITS(float); FLOAT_IDENTITY_TRAITS(double); + OPAQUE_IDENTITY_TRAITS(std::condition_variable); + OPAQUE_IDENTITY_TRAITS(std::fstream); + OPAQUE_IDENTITY_TRAITS(std::mutex); template<> struct DFHACK_EXPORT identity_traits { static bool_identity identity; @@ -566,16 +576,6 @@ namespace df static stl_string_identity *get() { return &identity; } }; - template<> struct DFHACK_EXPORT identity_traits { - static opaque_identity identity; - static opaque_identity *get() { return &identity; } - }; - - template<> struct DFHACK_EXPORT identity_traits { - static opaque_identity identity; - static opaque_identity *get() { return &identity; } - }; - template<> struct DFHACK_EXPORT identity_traits { static ptr_string_identity identity; static ptr_string_identity *get() { return &identity; } @@ -604,6 +604,7 @@ namespace df #undef NUMBER_IDENTITY_TRAITS #undef INTEGER_IDENTITY_TRAITS #undef FLOAT_IDENTITY_TRAITS +#undef OPAQUE_IDENTITY_TRAITS // Container declarations From 8b786b43446d3e50d3e0d906bc70ba65b70742bf Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 29 May 2023 01:12:35 -0400 Subject: [PATCH 7/7] Forward-declare types only used in DataIdentity.cpp --- library/DataIdentity.cpp | 2 ++ library/include/DataIdentity.h | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/library/DataIdentity.cpp b/library/DataIdentity.cpp index 0f85e5d95..03851520c 100644 --- a/library/DataIdentity.cpp +++ b/library/DataIdentity.cpp @@ -1,11 +1,13 @@ #include +#include #include #include #include #include #include "DataFuncs.h" +#include "DataIdentity.h" namespace df { #define NUMBER_IDENTITY_TRAITS(category, type, name) \ diff --git a/library/include/DataIdentity.h b/library/include/DataIdentity.h index 232b32108..be5466444 100644 --- a/library/include/DataIdentity.h +++ b/library/include/DataIdentity.h @@ -24,16 +24,19 @@ distribution. #pragma once -#include #include #include -#include #include #include #include #include "DataDefs.h" +namespace std { + class condition_variable; + class mutex; +}; + /* * Definitions of DFHack namespace structs used by generated headers. */