Manage the case EnvReal = EnvReal.
Since assigning one env to the other means deleting everything from the destination first, if dst == src then this would mean wiping the source clean as well. This is avoided by checking in the base class if src and dst objects are different and, even if they are, if they are not representing both the same global state.
This commit is contained in:
parent
8a7e42cd3c
commit
ad7e5c8c27
7 changed files with 188 additions and 5 deletions
148
src/StringCRC32.hpp
Normal file
148
src/StringCRC32.hpp
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
#ifndef id42C91D2875AE4E56BA61051619B58C03
|
||||||
|
#define id42C91D2875AE4E56BA61051619B58C03
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace duckcore {
|
||||||
|
class StringCRC32 {
|
||||||
|
struct FnvHashBase {
|
||||||
|
[[gnu::pure]] [[gnu::always_inline]]
|
||||||
|
static uint32_t Calculate ( const char parChar, uint32_t parCrc );
|
||||||
|
};
|
||||||
|
|
||||||
|
//Update step: crc_32_tab[(crc ^ ch) & 0xff] ^ (crc >> 8)
|
||||||
|
template <uint32_t N, uint32_t I>
|
||||||
|
struct FnvHash : private FnvHashBase {
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
static uint32_t Calculate ( const char (&str)[N], uint32_t crc ) {
|
||||||
|
const uint32_t prevcrc = FnvHash<N, I-1>::Calculate(str, crc);
|
||||||
|
return FnvHashBase::Calculate(str[I-1], prevcrc);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <unsigned int N>
|
||||||
|
struct FnvHash<N, 1> : private FnvHashBase {
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
static uint32_t Calculate ( const char (&str)[N], uint32_t crc ) {
|
||||||
|
return FnvHashBase::Calculate(str[0], crc);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstCharWrapper {
|
||||||
|
public:
|
||||||
|
ConstCharWrapper ( const char* parStr ) : str(parStr) { }
|
||||||
|
const char* const str;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
|
||||||
|
StringCRC32 ( ConstCharWrapper parStr );
|
||||||
|
|
||||||
|
template <unsigned int N>
|
||||||
|
[[gnu::always_inline]]
|
||||||
|
StringCRC32 ( const char (&str)[N] ) :
|
||||||
|
m_hash(~FnvHash<N, N>::Calculate(str, 0xffffffff))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
operator uint32_t ( void ) const { return m_hash; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t m_hash;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//This is meant to represent a list of bits that are set to 1
|
||||||
|
template <int N, typename T>
|
||||||
|
struct BitArray {
|
||||||
|
enum { value = N };
|
||||||
|
typedef T Next;
|
||||||
|
};
|
||||||
|
//Polynomial from zlib: {0,1,2,4,5,7,8,10,11,12,16,22,23,26} or 0xedb88320UL
|
||||||
|
// for (int poly = 0, n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||||
|
// poly |= (z_crc_t)1 << (31 - p[n]);
|
||||||
|
typedef BitArray<0, BitArray<1, BitArray<2, BitArray<4, BitArray<5,
|
||||||
|
BitArray<7, BitArray<8, BitArray<10, BitArray<11, BitArray<12,
|
||||||
|
BitArray<16, BitArray<22, BitArray<23,
|
||||||
|
BitArray<26, nullptr_t> > > > > > > > > > > > > > PolynomialBits;
|
||||||
|
template <typename P, int M>
|
||||||
|
struct MakePolynomial {
|
||||||
|
enum { value = (1 << (M - P::value)) bitor MakePolynomial<typename P::Next, M>::value };
|
||||||
|
};
|
||||||
|
template <int M>
|
||||||
|
struct MakePolynomial<nullptr_t, M> {
|
||||||
|
enum { value = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
//CRC32 algorithm from zlib:
|
||||||
|
// for (int n = 0; n < 256; n++) {
|
||||||
|
// c = n;
|
||||||
|
// for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||||
|
// crc_table[n] = c;
|
||||||
|
// }
|
||||||
|
template <int C, int S=8, uint32_t P=static_cast<uint32_t>(MakePolynomial<PolynomialBits, 31>::value)>
|
||||||
|
struct TableLookup {
|
||||||
|
static_assert(S > 1);
|
||||||
|
enum {
|
||||||
|
poly = P,
|
||||||
|
value = TableLookup<TableLookup<C, S-1, poly>::value, 1, poly>::value
|
||||||
|
};
|
||||||
|
};
|
||||||
|
template <int C, uint32_t P>
|
||||||
|
struct TableLookup<C, 1, P> {
|
||||||
|
enum {
|
||||||
|
poly = P,
|
||||||
|
value = ((C & 1) == 1 ? poly ^ (static_cast<uint32_t>(C) >> 1) : static_cast<uint32_t>(C) >> 1)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
inline uint32_t StringCRC32::FnvHashBase::Calculate (const char parChar, uint32_t parCrc) {
|
||||||
|
static const uint32_t crc_32_tab[256] = { /* CRC polynomial 0xedb88320 */
|
||||||
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||||
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||||
|
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||||
|
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||||
|
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||||
|
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||||
|
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||||
|
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||||
|
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||||
|
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||||
|
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||||
|
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||||
|
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||||
|
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||||
|
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||||
|
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||||
|
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||||
|
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||||
|
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||||
|
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||||
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||||
|
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||||
|
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||||
|
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||||
|
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||||
|
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||||
|
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||||
|
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||||
|
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||||
|
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||||
|
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||||
|
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||||
|
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||||
|
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||||
|
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||||
|
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||||
|
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||||
|
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||||
|
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||||
|
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||||
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||||
|
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||||
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||||
|
};
|
||||||
|
return crc_32_tab[(parCrc ^ parChar) & 0xff] ^ (parCrc >> 8);
|
||||||
|
}
|
||||||
|
} //namespace duckcore
|
||||||
|
|
||||||
|
#endif
|
|
@ -133,4 +133,16 @@ void EnvBase::clear_nolock (EnvBase& obj) noexcept {
|
||||||
call_noexcept([&](){obj.clear_implem(m);}, to_string_view(__func__));
|
call_noexcept([&](){obj.clear_implem(m);}, to_string_view(__func__));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnvBase::set_all_into (EnvBase& other) const {
|
||||||
|
const bool tg = this->is_global();
|
||||||
|
const bool og = other.is_global();
|
||||||
|
const uint32_t tc = this->class_identifier();
|
||||||
|
const uint32_t oc = other.class_identifier();
|
||||||
|
if ((tg and og and tc != oc) or
|
||||||
|
(not (tg and og) and this != &other)
|
||||||
|
) {
|
||||||
|
this->set_all_into_implem(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace duck {
|
namespace duck {
|
||||||
class EnvBase;
|
class EnvBase;
|
||||||
|
@ -77,7 +78,7 @@ namespace duck {
|
||||||
virtual std::mutex& mutex() const noexcept = 0;
|
virtual std::mutex& mutex() const noexcept = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void set_all_into (EnvBase& other) const = 0;
|
virtual void set_all_into_implem (EnvBase& other) const = 0;
|
||||||
static void set_all_into (const EnvBase& obj, EnvBase& other) { obj.set_all_into(other); }
|
static void set_all_into (const EnvBase& obj, EnvBase& other) { obj.set_all_into(other); }
|
||||||
virtual void clear_implem(Mutex& m) = 0;
|
virtual void clear_implem(Mutex& m) = 0;
|
||||||
static void clear_nolock (EnvBase& obj) noexcept;
|
static void clear_nolock (EnvBase& obj) noexcept;
|
||||||
|
@ -90,6 +91,12 @@ namespace duck {
|
||||||
virtual void unset_implem (std::string_view name, Mutex& m) = 0;
|
virtual void unset_implem (std::string_view name, Mutex& m) = 0;
|
||||||
virtual bool is_set_implem (std::string_view name, Mutex& m) const = 0;
|
virtual bool is_set_implem (std::string_view name, Mutex& m) const = 0;
|
||||||
virtual size_type size_implem(Mutex& m) const = 0;
|
virtual size_type size_implem(Mutex& m) const = 0;
|
||||||
|
|
||||||
|
virtual bool is_global() const noexcept = 0;
|
||||||
|
virtual uint32_t class_identifier() const noexcept = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void set_all_into (EnvBase& other) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "to_var_map.hpp"
|
#include "to_var_map.hpp"
|
||||||
#include "safe_print.hpp"
|
#include "safe_print.hpp"
|
||||||
#include "string_view_cat.hpp"
|
#include "string_view_cat.hpp"
|
||||||
|
#include "StringCRC32.hpp"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -155,7 +156,7 @@ std::mutex& EnvFake::mutex() const noexcept {
|
||||||
return m_mutex;
|
return m_mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnvFake::set_all_into (EnvBase& other) const {
|
void EnvFake::set_all_into_implem (EnvBase& other) const {
|
||||||
std::scoped_lock lock(m_mutex, other.mutex());
|
std::scoped_lock lock(m_mutex, other.mutex());
|
||||||
|
|
||||||
EnvBase::clear_nolock(other);
|
EnvBase::clear_nolock(other);
|
||||||
|
@ -168,4 +169,8 @@ EnvFake& EnvFake::operator= (const EnvBase& other) {
|
||||||
EnvBase::set_all_into(other, *this);
|
EnvBase::set_all_into(other, *this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t EnvFake::class_identifier() const noexcept {
|
||||||
|
return duckcore::StringCRC32(__func__);
|
||||||
|
}
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace duck {
|
||||||
virtual std::mutex& mutex() const noexcept override;
|
virtual std::mutex& mutex() const noexcept override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void set_all_into (EnvBase& other) const override;
|
virtual void set_all_into_implem (EnvBase& other) const override;
|
||||||
virtual void clear_implem(Mutex& m) override;
|
virtual void clear_implem(Mutex& m) override;
|
||||||
virtual std::optional<std::string_view> get_implem (std::string_view name, Mutex& m) const override;
|
virtual std::optional<std::string_view> get_implem (std::string_view name, Mutex& m) const override;
|
||||||
virtual std::string_view get_implem (std::string_view name, std::string_view def, Mutex& m) const override;
|
virtual std::string_view get_implem (std::string_view name, std::string_view def, Mutex& m) const override;
|
||||||
|
@ -50,6 +50,9 @@ namespace duck {
|
||||||
virtual bool is_set_implem (std::string_view name, Mutex& m) const override;
|
virtual bool is_set_implem (std::string_view name, Mutex& m) const override;
|
||||||
virtual size_type size_implem (Mutex& m) const override;
|
virtual size_type size_implem (Mutex& m) const override;
|
||||||
|
|
||||||
|
virtual bool is_global() const noexcept override { return false; }
|
||||||
|
virtual uint32_t class_identifier() const noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string_view, std::unique_ptr<char[]>> m_map_strong_cpy;
|
std::unordered_map<std::string_view, std::unique_ptr<char[]>> m_map_strong_cpy;
|
||||||
map_type m_map;
|
map_type m_map;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "env_real.hpp"
|
#include "env_real.hpp"
|
||||||
#include "string_view_cat.hpp"
|
#include "string_view_cat.hpp"
|
||||||
#include "safe_print.hpp"
|
#include "safe_print.hpp"
|
||||||
|
#include "StringCRC32.hpp"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -333,7 +334,7 @@ std::mutex& EnvReal::mutex() const noexcept {
|
||||||
return pointer_map().env_mutex();
|
return pointer_map().env_mutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnvReal::set_all_into (EnvBase& other) const {
|
void EnvReal::set_all_into_implem (EnvBase& other) const {
|
||||||
auto& pm = pointer_map();
|
auto& pm = pointer_map();
|
||||||
std::scoped_lock lock(pm.env_mutex(), other.mutex());
|
std::scoped_lock lock(pm.env_mutex(), other.mutex());
|
||||||
|
|
||||||
|
@ -342,4 +343,8 @@ void EnvReal::set_all_into (EnvBase& other) const {
|
||||||
EnvBase::set_nolock(other, keyval.first, keyval.second);
|
EnvBase::set_nolock(other, keyval.first, keyval.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t EnvReal::class_identifier() const noexcept {
|
||||||
|
return duckcore::StringCRC32(__func__);
|
||||||
|
}
|
||||||
} //namespace duck
|
} //namespace duck
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace duck {
|
||||||
virtual std::mutex& mutex() const noexcept override;
|
virtual std::mutex& mutex() const noexcept override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void set_all_into (EnvBase& other) const override;
|
virtual void set_all_into_implem (EnvBase& other) const override;
|
||||||
virtual void clear_implem(Mutex& m) override;
|
virtual void clear_implem(Mutex& m) override;
|
||||||
virtual std::optional<std::string_view> get_implem (std::string_view name, Mutex& m) const override;
|
virtual std::optional<std::string_view> get_implem (std::string_view name, Mutex& m) const override;
|
||||||
virtual std::string_view get_implem (std::string_view name, std::string_view def, Mutex& m) const override;
|
virtual std::string_view get_implem (std::string_view name, std::string_view def, Mutex& m) const override;
|
||||||
|
@ -71,6 +71,9 @@ namespace duck {
|
||||||
virtual bool is_set_implem (std::string_view name, Mutex& m) const override;
|
virtual bool is_set_implem (std::string_view name, Mutex& m) const override;
|
||||||
virtual size_type size_implem(Mutex& m) const override;
|
virtual size_type size_implem(Mutex& m) const override;
|
||||||
|
|
||||||
|
virtual bool is_global() const noexcept override { return true; }
|
||||||
|
virtual uint32_t class_identifier() const noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* raw_fetch_env (std::string_view name, Mutex& m) const noexcept;
|
const char* raw_fetch_env (std::string_view name, Mutex& m) const noexcept;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue