mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	common: Miscellaneous cleanups (#7239)
* code: Remove some old msvc workarounds * android: Upgrade to NDK 26 * Allows access to newer libc++ * common/swap: Make use of std::endian Allows removing a bunch of defines in favor of a two liner. * common: Remove misc.cpp * GetLastErrorMsg has been in error.h for a while and also helps removing a depedency from a hot header like common_funcs * common: use SetThreadDescription API for thread names * common: Remove linear disk cache * Has never been used? * bit_set: Make constexpr * ring_buffer: Use feature macro * bit_set: Use <bit> and concepts * gsp_gpu: Restore comment * core: Ignore GCC warning --------- Co-authored-by: Lioncash <mathew1800@gmail.com> Co-authored-by: Liam <byteslice@airmail.cc>
This commit is contained in:
		
							parent
							
								
									15ea0c6336
								
							
						
					
					
						commit
						2b20082581
					
				
					 15 changed files with 50 additions and 426 deletions
				
			
		|  | @ -90,7 +90,6 @@ add_library(citra_common STATIC | |||
|     file_util.cpp | ||||
|     file_util.h | ||||
|     hash.h | ||||
|     linear_disk_cache.h | ||||
|     literals.h | ||||
|     logging/backend.cpp | ||||
|     logging/backend.h | ||||
|  | @ -110,7 +109,6 @@ add_library(citra_common STATIC | |||
|     microprofile.cpp | ||||
|     microprofile.h | ||||
|     microprofileui.h | ||||
|     misc.cpp | ||||
|     param_package.cpp | ||||
|     param_package.h | ||||
|     polyfill_thread.h | ||||
|  |  | |||
|  | @ -2,78 +2,14 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <bit> | ||||
| #include <cstddef> | ||||
| #ifdef _WIN32 | ||||
| #include <intrin.h> | ||||
| #endif | ||||
| #include <initializer_list> | ||||
| #include <new> | ||||
| #include <type_traits> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| // namespace avoids conflict with OS X Carbon; don't use BitSet<T> directly
 | ||||
| namespace Common { | ||||
| 
 | ||||
| // Helper functions:
 | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| template <typename T> | ||||
| static inline int CountSetBits(T v) { | ||||
|     // from https://graphics.stanford.edu/~seander/bithacks.html
 | ||||
|     // GCC has this built in, but MSVC's intrinsic will only emit the actual
 | ||||
|     // POPCNT instruction, which we're not depending on
 | ||||
|     v = v - ((v >> 1) & (T) ~(T)0 / 3); | ||||
|     v = (v & (T) ~(T)0 / 15 * 3) + ((v >> 2) & (T) ~(T)0 / 15 * 3); | ||||
|     v = (v + (v >> 4)) & (T) ~(T)0 / 255 * 15; | ||||
|     return (T)(v * ((T) ~(T)0 / 255)) >> (sizeof(T) - 1) * 8; | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u8 val) { | ||||
|     unsigned long index; | ||||
|     _BitScanForward(&index, val); | ||||
|     return (int)index; | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u16 val) { | ||||
|     unsigned long index; | ||||
|     _BitScanForward(&index, val); | ||||
|     return (int)index; | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u32 val) { | ||||
|     unsigned long index; | ||||
|     _BitScanForward(&index, val); | ||||
|     return (int)index; | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u64 val) { | ||||
|     unsigned long index; | ||||
|     _BitScanForward64(&index, val); | ||||
|     return (int)index; | ||||
| } | ||||
| #else | ||||
| static inline int CountSetBits(u8 val) { | ||||
|     return __builtin_popcount(val); | ||||
| } | ||||
| static inline int CountSetBits(u16 val) { | ||||
|     return __builtin_popcount(val); | ||||
| } | ||||
| static inline int CountSetBits(u32 val) { | ||||
|     return __builtin_popcount(val); | ||||
| } | ||||
| static inline int CountSetBits(u64 val) { | ||||
|     return __builtin_popcountll(val); | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u8 val) { | ||||
|     return __builtin_ctz(val); | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u16 val) { | ||||
|     return __builtin_ctz(val); | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u32 val) { | ||||
|     return __builtin_ctz(val); | ||||
| } | ||||
| static inline int LeastSignificantSetBit(u64 val) { | ||||
|     return __builtin_ctzll(val); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| // Similar to std::bitset, this is a class which encapsulates a bitset, i.e.
 | ||||
| // using the set bits of an integer to represent a set of integers.  Like that
 | ||||
| // class, it acts like an array of bools:
 | ||||
|  | @ -92,22 +28,19 @@ static inline int LeastSignificantSetBit(u64 val) { | |||
| //   operation.)
 | ||||
| // - Counting set bits using .Count() - see comment on that method.
 | ||||
| 
 | ||||
| // TODO: use constexpr when MSVC gets out of the Dark Ages
 | ||||
| 
 | ||||
| template <typename IntTy> | ||||
|     requires std::is_unsigned_v<IntTy> | ||||
| class BitSet { | ||||
|     static_assert(!std::is_signed_v<IntTy>, "BitSet should not be used with signed types"); | ||||
| 
 | ||||
| public: | ||||
|     // A reference to a particular bit, returned from operator[].
 | ||||
|     class Ref { | ||||
|     public: | ||||
|         Ref(Ref&& other) : m_bs(other.m_bs), m_mask(other.m_mask) {} | ||||
|         Ref(BitSet* bs, IntTy mask) : m_bs(bs), m_mask(mask) {} | ||||
|         operator bool() const { | ||||
|         constexpr Ref(Ref&& other) : m_bs(other.m_bs), m_mask(other.m_mask) {} | ||||
|         constexpr Ref(BitSet* bs, IntTy mask) : m_bs(bs), m_mask(mask) {} | ||||
|         constexpr operator bool() const { | ||||
|             return (m_bs->m_val & m_mask) != 0; | ||||
|         } | ||||
|         bool operator=(bool set) { | ||||
|         constexpr bool operator=(bool set) { | ||||
|             m_bs->m_val = (m_bs->m_val & ~m_mask) | (set ? m_mask : 0); | ||||
|             return set; | ||||
|         } | ||||
|  | @ -120,26 +53,26 @@ public: | |||
|     // A STL-like iterator is required to be able to use range-based for loops.
 | ||||
|     class Iterator { | ||||
|     public: | ||||
|         Iterator(const Iterator& other) : m_val(other.m_val) {} | ||||
|         Iterator(IntTy val) : m_val(val) {} | ||||
|         int operator*() { | ||||
|         constexpr Iterator(const Iterator& other) : m_val(other.m_val) {} | ||||
|         constexpr Iterator(IntTy val) : m_val(val) {} | ||||
|         constexpr int operator*() { | ||||
|             // This will never be called when m_val == 0, because that would be the end() iterator
 | ||||
|             return LeastSignificantSetBit(m_val); | ||||
|             return std::countr_zero(m_val); | ||||
|         } | ||||
|         Iterator& operator++() { | ||||
|         constexpr Iterator& operator++() { | ||||
|             // Unset least significant set bit
 | ||||
|             m_val &= m_val - IntTy(1); | ||||
|             return *this; | ||||
|         } | ||||
|         Iterator operator++(int _) { | ||||
|         constexpr Iterator operator++(int) { | ||||
|             Iterator other(*this); | ||||
|             ++*this; | ||||
|             return other; | ||||
|         } | ||||
|         bool operator==(Iterator other) const { | ||||
|         constexpr bool operator==(Iterator other) const { | ||||
|             return m_val == other.m_val; | ||||
|         } | ||||
|         bool operator!=(Iterator other) const { | ||||
|         constexpr bool operator!=(Iterator other) const { | ||||
|             return m_val != other.m_val; | ||||
|         } | ||||
| 
 | ||||
|  | @ -147,74 +80,69 @@ public: | |||
|         IntTy m_val; | ||||
|     }; | ||||
| 
 | ||||
|     BitSet() : m_val(0) {} | ||||
|     explicit BitSet(IntTy val) : m_val(val) {} | ||||
|     BitSet(std::initializer_list<int> init) { | ||||
|     constexpr BitSet() : m_val(0) {} | ||||
|     constexpr explicit BitSet(IntTy val) : m_val(val) {} | ||||
|     constexpr BitSet(std::initializer_list<int> init) { | ||||
|         m_val = 0; | ||||
|         for (int bit : init) | ||||
|             m_val |= (IntTy)1 << bit; | ||||
|     } | ||||
| 
 | ||||
|     static BitSet AllTrue(std::size_t count) { | ||||
|     constexpr static BitSet AllTrue(std::size_t count) { | ||||
|         return BitSet(count == sizeof(IntTy) * 8 ? ~(IntTy)0 : (((IntTy)1 << count) - 1)); | ||||
|     } | ||||
| 
 | ||||
|     Ref operator[](std::size_t bit) { | ||||
|     constexpr Ref operator[](std::size_t bit) { | ||||
|         return Ref(this, (IntTy)1 << bit); | ||||
|     } | ||||
|     const Ref operator[](std::size_t bit) const { | ||||
|     constexpr const Ref operator[](std::size_t bit) const { | ||||
|         return (*const_cast<BitSet*>(this))[bit]; | ||||
|     } | ||||
|     bool operator==(BitSet other) const { | ||||
|     constexpr bool operator==(BitSet other) const { | ||||
|         return m_val == other.m_val; | ||||
|     } | ||||
|     bool operator!=(BitSet other) const { | ||||
|     constexpr bool operator!=(BitSet other) const { | ||||
|         return m_val != other.m_val; | ||||
|     } | ||||
|     bool operator<(BitSet other) const { | ||||
|     constexpr bool operator<(BitSet other) const { | ||||
|         return m_val < other.m_val; | ||||
|     } | ||||
|     bool operator>(BitSet other) const { | ||||
|     constexpr bool operator>(BitSet other) const { | ||||
|         return m_val > other.m_val; | ||||
|     } | ||||
|     BitSet operator|(BitSet other) const { | ||||
|     constexpr BitSet operator|(BitSet other) const { | ||||
|         return BitSet(m_val | other.m_val); | ||||
|     } | ||||
|     BitSet operator&(BitSet other) const { | ||||
|     constexpr BitSet operator&(BitSet other) const { | ||||
|         return BitSet(m_val & other.m_val); | ||||
|     } | ||||
|     BitSet operator^(BitSet other) const { | ||||
|     constexpr BitSet operator^(BitSet other) const { | ||||
|         return BitSet(m_val ^ other.m_val); | ||||
|     } | ||||
|     BitSet operator~() const { | ||||
|     constexpr BitSet operator~() const { | ||||
|         return BitSet(~m_val); | ||||
|     } | ||||
|     BitSet& operator|=(BitSet other) { | ||||
|     constexpr BitSet& operator|=(BitSet other) { | ||||
|         return *this = *this | other; | ||||
|     } | ||||
|     BitSet& operator&=(BitSet other) { | ||||
|     constexpr BitSet& operator&=(BitSet other) { | ||||
|         return *this = *this & other; | ||||
|     } | ||||
|     BitSet& operator^=(BitSet other) { | ||||
|     constexpr BitSet& operator^=(BitSet other) { | ||||
|         return *this = *this ^ other; | ||||
|     } | ||||
|     operator u32() = delete; | ||||
|     operator bool() { | ||||
|     constexpr operator bool() { | ||||
|         return m_val != 0; | ||||
|     } | ||||
| 
 | ||||
|     // Warning: Even though on modern CPUs this is a single fast instruction,
 | ||||
|     // Dolphin's official builds do not currently assume POPCNT support on x86,
 | ||||
|     // so slower explicit bit twiddling is generated.  Still should generally
 | ||||
|     // be faster than a loop.
 | ||||
|     unsigned int Count() const { | ||||
|         return CountSetBits(m_val); | ||||
|     constexpr u32 Count() const { | ||||
|         return std::popcount(m_val); | ||||
|     } | ||||
| 
 | ||||
|     Iterator begin() const { | ||||
|     constexpr Iterator begin() const { | ||||
|         return Iterator(m_val); | ||||
|     } | ||||
|     Iterator end() const { | ||||
|     constexpr Iterator end() const { | ||||
|         return Iterator(0); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | ||||
|  | @ -46,14 +45,8 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | |||
| #endif | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| #if (_MSC_VER < 1900) | ||||
| // Function Cross-Compatibility
 | ||||
| #define snprintf _snprintf | ||||
| #endif | ||||
| 
 | ||||
| // Locale Cross-Compatibility
 | ||||
| #define locale_t _locale_t | ||||
| 
 | ||||
| #endif // _MSC_VER
 | ||||
| 
 | ||||
| #define DECLARE_ENUM_FLAG_OPERATORS(type)                                                          \ | ||||
|  | @ -109,9 +102,3 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | |||
|         using T = std::underlying_type_t<type>;                                                    \ | ||||
|         return static_cast<T>(key) == 0;                                                           \ | ||||
|     } | ||||
| 
 | ||||
| // Generic function to get last error message.
 | ||||
| // Call directly after the command or use the error num.
 | ||||
| // This function might change the error code.
 | ||||
| // Defined in Misc.cpp.
 | ||||
| [[nodiscard]] std::string GetLastErrorMsg(); | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "common/assert.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_paths.h" | ||||
| #include "common/error.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/scope_exit.h" | ||||
|  | @ -90,6 +91,8 @@ | |||
| // REMEMBER: strdup considered harmful!
 | ||||
| namespace FileUtil { | ||||
| 
 | ||||
| using Common::GetLastErrorMsg; | ||||
| 
 | ||||
| // Remove any ending forward slashes from directory paths
 | ||||
| // Modifies argument.
 | ||||
| static void StripTailDirSlashes(std::string& fname) { | ||||
|  |  | |||
|  | @ -1,168 +0,0 @@ | |||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <fstream> | ||||
| #include <vector> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| // defined in Version.cpp
 | ||||
| extern const char* scm_rev_git_str; | ||||
| 
 | ||||
| // On disk format:
 | ||||
| // header{
 | ||||
| // u32 'DCAC';
 | ||||
| // u32 version;  // svn_rev
 | ||||
| // u16 sizeof(key_type);
 | ||||
| // u16 sizeof(value_type);
 | ||||
| //}
 | ||||
| 
 | ||||
| // key_value_pair{
 | ||||
| // u32 value_size;
 | ||||
| // key_type   key;
 | ||||
| // value_type[value_size]   value;
 | ||||
| //}
 | ||||
| 
 | ||||
| template <typename K, typename V> | ||||
| class LinearDiskCacheReader { | ||||
| public: | ||||
|     virtual void Read(const K& key, const V* value, u32 value_size) = 0; | ||||
| }; | ||||
| 
 | ||||
| // Dead simple unsorted key-value store with append functionality.
 | ||||
| // No random read functionality, all reading is done in OpenAndRead.
 | ||||
| // Keys and values can contain any characters, including \0.
 | ||||
| //
 | ||||
| // Suitable for caching generated shader bytecode between executions.
 | ||||
| // Not tuned for extreme performance but should be reasonably fast.
 | ||||
| // Does not support keys or values larger than 2GB, which should be reasonable.
 | ||||
| // Keys must have non-zero length; values can have zero length.
 | ||||
| 
 | ||||
| // K and V are some POD type
 | ||||
| // K : the key type
 | ||||
| // V : value array type
 | ||||
| template <typename K, typename V> | ||||
| class LinearDiskCache { | ||||
| public: | ||||
|     // return number of read entries
 | ||||
|     u32 OpenAndRead(const char* filename, LinearDiskCacheReader<K, V>& reader) { | ||||
|         using std::ios_base; | ||||
| 
 | ||||
|         // close any currently opened file
 | ||||
|         Close(); | ||||
|         m_num_entries = 0; | ||||
| 
 | ||||
|         // try opening for reading/writing
 | ||||
|         OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary); | ||||
| 
 | ||||
|         m_file.seekg(0, std::ios::end); | ||||
|         std::fstream::pos_type end_pos = m_file.tellg(); | ||||
|         m_file.seekg(0, std::ios::beg); | ||||
|         std::fstream::pos_type start_pos = m_file.tellg(); | ||||
|         std::streamoff file_size = end_pos - start_pos; | ||||
| 
 | ||||
|         if (m_file.is_open() && ValidateHeader()) { | ||||
|             // good header, read some key/value pairs
 | ||||
|             K key; | ||||
| 
 | ||||
|             std::vector<V> value; | ||||
|             u32 value_size; | ||||
|             u32 entry_number; | ||||
| 
 | ||||
|             std::fstream::pos_type last_pos = m_file.tellg(); | ||||
| 
 | ||||
|             while (Read(&value_size)) { | ||||
|                 std::streamoff next_extent = | ||||
|                     (last_pos - start_pos) + sizeof(value_size) + value_size; | ||||
|                 if (next_extent > file_size) | ||||
|                     break; | ||||
| 
 | ||||
|                 value.clear(); | ||||
|                 value.resize(value_size); | ||||
| 
 | ||||
|                 // read key/value and pass to reader
 | ||||
|                 if (Read(&key) && Read(value.data(), value_size) && Read(&entry_number) && | ||||
|                     entry_number == m_num_entries + 1) { | ||||
|                     reader.Read(key, value.data(), value_size); | ||||
|                 } else { | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 m_num_entries++; | ||||
|                 last_pos = m_file.tellg(); | ||||
|             } | ||||
|             m_file.seekp(last_pos); | ||||
|             m_file.clear(); | ||||
| 
 | ||||
|             value.clear(); | ||||
|             return m_num_entries; | ||||
|         } | ||||
| 
 | ||||
|         // failed to open file for reading or bad header
 | ||||
|         // close and recreate file
 | ||||
|         Close(); | ||||
|         m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary); | ||||
|         WriteHeader(); | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     void Sync() { | ||||
|         m_file.flush(); | ||||
|     } | ||||
| 
 | ||||
|     void Close() { | ||||
|         if (m_file.is_open()) | ||||
|             m_file.close(); | ||||
|         // clear any error flags
 | ||||
|         m_file.clear(); | ||||
|     } | ||||
| 
 | ||||
|     // Appends a key-value pair to the store.
 | ||||
|     void Append(const K& key, const V* value, u32 value_size) { | ||||
|         // TODO: Should do a check that we don't already have "key"? (I think each caller does that
 | ||||
|         // already.)
 | ||||
|         Write(&value_size); | ||||
|         Write(&key); | ||||
|         Write(value, value_size); | ||||
|         m_num_entries++; | ||||
|         Write(&m_num_entries); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     void WriteHeader() { | ||||
|         Write(&m_header); | ||||
|     } | ||||
| 
 | ||||
|     bool ValidateHeader() { | ||||
|         char file_header[sizeof(Header)]; | ||||
| 
 | ||||
|         return (Read(file_header, sizeof(Header)) && | ||||
|                 !memcmp((const char*)&m_header, file_header, sizeof(Header))); | ||||
|     } | ||||
| 
 | ||||
|     template <typename D> | ||||
|     bool Write(const D* data, u32 count = 1) { | ||||
|         return m_file.write((const char*)data, count * sizeof(D)).good(); | ||||
|     } | ||||
| 
 | ||||
|     template <typename D> | ||||
|     bool Read(const D* data, u32 count = 1) { | ||||
|         return m_file.read((char*)data, count * sizeof(D)).good(); | ||||
|     } | ||||
| 
 | ||||
|     struct Header { | ||||
|         Header() : id(*(u32*)"DCAC"), key_t_size(sizeof(K)), value_t_size(sizeof(V)) { | ||||
|             std::memcpy(ver, scm_rev_git_str, 40); | ||||
|         } | ||||
| 
 | ||||
|         const u32 id; | ||||
|         const u16 key_t_size, value_t_size; | ||||
|         char ver[40]; | ||||
| 
 | ||||
|     } m_header; | ||||
| 
 | ||||
|     std::fstream m_file; | ||||
|     u32 m_num_entries; | ||||
| }; | ||||
|  | @ -1,48 +0,0 @@ | |||
| // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <cstddef> | ||||
| #ifdef _WIN32 | ||||
| #include <windows.h> | ||||
| #else | ||||
| #include <cerrno> | ||||
| #include <cstring> | ||||
| #endif | ||||
| 
 | ||||
| #include "common/common_funcs.h" | ||||
| 
 | ||||
| // Generic function to get last error message.
 | ||||
| // Call directly after the command or use the error num.
 | ||||
| // This function might change the error code.
 | ||||
| std::string GetLastErrorMsg() { | ||||
| #ifdef _WIN32 | ||||
|     LPSTR err_str; | ||||
| 
 | ||||
|     DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | | ||||
|                                    FORMAT_MESSAGE_IGNORE_INSERTS, | ||||
|                                nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||||
|                                reinterpret_cast<LPSTR>(&err_str), 1, nullptr); | ||||
|     if (!res) { | ||||
|         return "(FormatMessageA failed to format error)"; | ||||
|     } | ||||
|     std::string ret(err_str); | ||||
|     LocalFree(err_str); | ||||
|     return ret; | ||||
| #else | ||||
|     char err_str[255]; | ||||
| #if (defined(__GLIBC__) || __ANDROID_API__ >= 23) &&                                               \ | ||||
|     (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) | ||||
|     // Thread safe (GNU-specific)
 | ||||
|     const char* str = strerror_r(errno, err_str, sizeof(err_str)); | ||||
|     return std::string(str); | ||||
| #else | ||||
|     // Thread safe (XSI-compliant)
 | ||||
|     int second_err = strerror_r(errno, err_str, sizeof(err_str)); | ||||
|     if (second_err != 0) { | ||||
|         return "(strerror_r failed to format error)"; | ||||
|     } | ||||
|     return std::string(err_str); | ||||
| #endif // GLIBC etc.
 | ||||
| #endif // _WIN32
 | ||||
| } | ||||
|  | @ -105,9 +105,7 @@ public: | |||
| private: | ||||
|     // It is important to separate the below atomics for performance reasons:
 | ||||
|     // Having them on the same cache-line would result in false-sharing between them.
 | ||||
|     // TODO: Remove this ifdef whenever clang and GCC support
 | ||||
|     //       std::hardware_destructive_interference_size.
 | ||||
| #if defined(_MSC_VER) && _MSC_VER >= 1911 | ||||
| #ifdef __cpp_lib_hardware_interference_size | ||||
|     static constexpr std::size_t padding_size = | ||||
|         std::hardware_destructive_interference_size - sizeof(std::atomic_size_t); | ||||
| #else | ||||
|  |  | |||
|  | @ -17,43 +17,14 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <type_traits> | ||||
| 
 | ||||
| #if defined(_MSC_VER) | ||||
| #include <cstdlib> | ||||
| #endif | ||||
| #include <bit> | ||||
| #include <cstring> | ||||
| #include <type_traits> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| // GCC
 | ||||
| #ifdef __GNUC__ | ||||
| 
 | ||||
| #if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) && !defined(COMMON_LITTLE_ENDIAN) | ||||
| #define COMMON_LITTLE_ENDIAN 1 | ||||
| #elif __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) && !defined(COMMON_BIG_ENDIAN) | ||||
| #define COMMON_BIG_ENDIAN 1 | ||||
| #endif | ||||
| 
 | ||||
| // LLVM/clang
 | ||||
| #elif defined(__clang__) | ||||
| 
 | ||||
| #if __LITTLE_ENDIAN__ && !defined(COMMON_LITTLE_ENDIAN) | ||||
| #define COMMON_LITTLE_ENDIAN 1 | ||||
| #elif __BIG_ENDIAN__ && !defined(COMMON_BIG_ENDIAN) | ||||
| #define COMMON_BIG_ENDIAN 1 | ||||
| #endif | ||||
| 
 | ||||
| // MSVC
 | ||||
| #elif defined(_MSC_VER) && !defined(COMMON_BIG_ENDIAN) && !defined(COMMON_LITTLE_ENDIAN) | ||||
| 
 | ||||
| #define COMMON_LITTLE_ENDIAN 1 | ||||
| #endif | ||||
| 
 | ||||
| // Worst case, default to little endian.
 | ||||
| #if !COMMON_BIG_ENDIAN && !COMMON_LITTLE_ENDIAN | ||||
| #define COMMON_LITTLE_ENDIAN 1 | ||||
| #endif | ||||
| 
 | ||||
| namespace Common { | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
|  | @ -675,17 +646,8 @@ struct AddEndian<T, SwapTag> { | |||
| }; | ||||
| 
 | ||||
| // Alias LETag/BETag as KeepTag/SwapTag depending on the system
 | ||||
| #if COMMON_LITTLE_ENDIAN | ||||
| 
 | ||||
| using LETag = KeepTag; | ||||
| using BETag = SwapTag; | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| using BETag = KeepTag; | ||||
| using LETag = SwapTag; | ||||
| 
 | ||||
| #endif | ||||
| using LETag = std::conditional_t<std::endian::native == std::endian::little, KeepTag, SwapTag>; | ||||
| using BETag = std::conditional_t<std::endian::native == std::endian::big, KeepTag, SwapTag>; | ||||
| 
 | ||||
| // Aliases for LE types
 | ||||
| using u16_le = AddEndian<u16, LETag>::type; | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
| #include <mach/mach.h> | ||||
| #elif defined(_WIN32) | ||||
| #include <windows.h> | ||||
| #include "common/string_util.h" | ||||
| #else | ||||
| #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) | ||||
| #include <pthread_np.h> | ||||
|  | @ -82,29 +83,8 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) { | |||
| #ifdef _MSC_VER | ||||
| 
 | ||||
| // Sets the debugger-visible name of the current thread.
 | ||||
| // Uses trick documented in:
 | ||||
| // https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
 | ||||
| void SetCurrentThreadName(const char* name) { | ||||
|     static const DWORD MS_VC_EXCEPTION = 0x406D1388; | ||||
| 
 | ||||
| #pragma pack(push, 8) | ||||
|     struct THREADNAME_INFO { | ||||
|         DWORD dwType;     // must be 0x1000
 | ||||
|         LPCSTR szName;    // pointer to name (in user addr space)
 | ||||
|         DWORD dwThreadID; // thread ID (-1=caller thread)
 | ||||
|         DWORD dwFlags;    // reserved for future use, must be zero
 | ||||
|     } info; | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
|     info.dwType = 0x1000; | ||||
|     info.szName = name; | ||||
|     info.dwThreadID = std::numeric_limits<DWORD>::max(); | ||||
|     info.dwFlags = 0; | ||||
| 
 | ||||
|     __try { | ||||
|         RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); | ||||
|     } __except (EXCEPTION_CONTINUE_EXECUTION) { | ||||
|     } | ||||
|     SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data()); | ||||
| } | ||||
| 
 | ||||
| #else // !MSVC_VER, so must be POSIX threads
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue