Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules6
m---------include/boost/afio/boost-lite0
m---------include/boost/afio/gsl-lite0
m---------include/boost/afio/outcome0
-rw-r--r--include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp10
-rw-r--r--include/boost/afio/v2.0/algorithm/shared_fs_mutex/base.hpp17
-rw-r--r--include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp2
-rw-r--r--include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp2
-rw-r--r--include/boost/afio/v2.0/config.hpp8
-rw-r--r--include/boost/afio/v2.0/detail/impl/windows/utils.ipp527
-rw-r--r--include/boost/afio/v2.0/utils.hpp472
m---------test/kerneltest0
-rw-r--r--test/tests/shared_fs_mutex.cpp5
13 files changed, 23 insertions, 1026 deletions
diff --git a/.gitmodules b/.gitmodules
index 40de0f57..36346270 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -10,12 +10,6 @@
branch = master
fetchRecurseSubmodules = true
ignore = untracked
-[submodule "include/boost/afio/gsl-lite"]
- path = include/boost/afio/gsl-lite
- url = https://github.com/martinmoene/gsl-lite.git
- branch = master
- fetchRecurseSubmodules = true
- ignore = untracked
[submodule "include/boost/afio/outcome"]
path = include/boost/afio/outcome
url = https://github.com/ned14/boost.outcome.git
diff --git a/include/boost/afio/boost-lite b/include/boost/afio/boost-lite
-Subproject 447601b03f68a52b181bad848e4b46b97386bf7
+Subproject fca658ace4399663912f77d52bb7dc0310c1f49
diff --git a/include/boost/afio/gsl-lite b/include/boost/afio/gsl-lite
deleted file mode 160000
-Subproject f436d33188b0117c1ecaa40ad9ebadabfdc69c3
diff --git a/include/boost/afio/outcome b/include/boost/afio/outcome
-Subproject bbf2bbafa512d64d79ab9e5d05adbc389c315ea
+Subproject bd8560354cfd1e2e26039f411685d2111c275b7
diff --git a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
index c3beb32d..d73c2c59 100644
--- a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
+++ b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
@@ -148,7 +148,7 @@ namespace algorithm
else
stl11::this_thread::yield();
// No timeout as this should very rarely block for any significant length of time
- } while(_header.hash != utils::fast_hash::hash(((char *) &_header) + 16, sizeof(_header) - 16));
+ } while(_header.hash != boost_lite::algorithm::hash::fast_hash::hash(((char *) &_header) + 16, sizeof(_header) - 16));
return make_result<void>();
}
@@ -201,7 +201,7 @@ namespace algorithm
header.first_known_good = sizeof(header);
header.first_after_hole_punch = sizeof(header);
if(!skip_hashing)
- header.hash = utils::fast_hash::hash(((char *) &header) + 16, sizeof(header) - 16);
+ header.hash = boost_lite::algorithm::hash::fast_hash::hash(((char *) &header) + 16, sizeof(header) - 16);
BOOST_OUTCOME_FILTER_ERROR(_, ret.write(0, (char *) &header, sizeof(header)));
(void) _;
}
@@ -245,7 +245,7 @@ namespace algorithm
lock_request.items = out.entities.size();
memcpy(lock_request.entities, out.entities.data(), sizeof(lock_request.entities[0]) * out.entities.size());
if(!_skip_hashing)
- lock_request.hash = utils::fast_hash::hash(((char *) &lock_request) + 16, sizeof(lock_request) - 16);
+ lock_request.hash = boost_lite::algorithm::hash::fast_hash::hash(((char *) &lock_request) + 16, sizeof(lock_request) - 16);
// My lock request will be the file's current length or higher
BOOST_OUTCOME_FILTER_ERROR(my_lock_request_offset, _h.length());
{
@@ -336,7 +336,7 @@ namespace algorithm
// If record hash doesn't match contents it's a torn read, reload
if(!_skip_hashing)
{
- if(record->hash != utils::fast_hash::hash(((char *) record) + 16, sizeof(atomic_append_detail::lock_request) - 16))
+ if(record->hash != boost_lite::algorithm::hash::fast_hash::hash(((char *) record) + 16, sizeof(atomic_append_detail::lock_request) - 16))
goto reload;
}
@@ -479,7 +479,7 @@ namespace algorithm
}
++_header.generation;
if(!_skip_hashing)
- _header.hash = utils::fast_hash::hash(((char *) &_header) + 16, sizeof(_header) - 16);
+ _header.hash = boost_lite::algorithm::hash::fast_hash::hash(((char *) &_header) + 16, sizeof(_header) - 16);
// Rewrite the first part of the header only
(void) _h.write(0, (char *) &_header, 48);
}
diff --git a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/base.hpp b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/base.hpp
index 7d429a48..83e72147 100644
--- a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/base.hpp
+++ b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/base.hpp
@@ -33,7 +33,8 @@ DEALINGS IN THE SOFTWARE.
#define BOOST_AFIO_SHARED_FS_MUTEX_BASE_HPP
#include "../../handle.hpp"
-#include "../../utils.hpp"
+
+#include "../boost-lite/include/algorithm/hash.hpp"
//! \file base.hpp Provides algorithm::shared_fs_mutex::shared_fs_mutex
@@ -47,7 +48,7 @@ namespace algorithm
//! Unsigned 64 bit integer
using uint64 = unsigned long long;
//! Unsigned 128 bit integer
- using uint128 = utils::uint128;
+ using uint128 = boost_lite::integers128::uint128;
/*! \class shared_fs_mutex
\brief Abstract base class for an object which protects shared filing system resources
@@ -98,14 +99,6 @@ namespace algorithm
using entities_type = span<entity_type>;
protected:
-#ifdef __cpp_relaxed_constexpr
- static constexpr bool _entity_type_endian_check()
- {
- entity_type v(0, true);
- return v._init != 1;
- }
- static_assert(_entity_type_endian_check(), "entity_type.exclusive is setting the bottom bit, endian problems?");
-#endif
constexpr shared_fs_mutex() {}
public:
@@ -114,13 +107,13 @@ namespace algorithm
//! Generates an entity id from a sequence of bytes
entity_type entity_from_buffer(const char *buffer, size_t bytes, bool exclusive = true) noexcept
{
- uint128 hash = utils::fast_hash::hash(buffer, bytes);
+ uint128 hash = boost_lite::algorithm::hash::fast_hash::hash(buffer, bytes);
return entity_type(hash.as_longlongs[0] ^ hash.as_longlongs[1], exclusive);
}
//! Generates an entity id from a string
template <typename T> entity_type entity_from_string(const std::basic_string<T> &str, bool exclusive = true) noexcept
{
- uint128 hash = utils::fast_hash::hash(str);
+ uint128 hash = boost_lite::algorithm::hash::fast_hash::hash(str);
return entity_type(hash.as_longlongs[0] ^ hash.as_longlongs[1], exclusive);
}
//! Generates a cryptographically random entity id.
diff --git a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
index 546390fe..58517b1a 100644
--- a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
+++ b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
@@ -133,7 +133,7 @@ namespace algorithm
for(n = 0; n < out.entities.size(); n++)
{
auto v = out.entities[n].value;
- entity_paths[n] = _path / utils::to_hex_string(span<char>((char *) &v, 8));
+ entity_paths[n] = _path / boost_lite::algorithm::string::to_hex_string(span<char>((char *) &v, 8));
}
_hs.resize(out.entities.size());
do
diff --git a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
index 5734dd78..ee1e995b 100644
--- a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
+++ b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
@@ -292,7 +292,7 @@ namespace algorithm
unsigned exclusive : 1;
};
// Create a cache of entities to their indices, eliding collisions where necessary
- static span<_entity_idx> _hash_entities(_entity_idx alignas(16) * entity_to_idx, entities_type &entities)
+ static span<_entity_idx> _hash_entities(_entity_idx *entity_to_idx, entities_type &entities)
{
_entity_idx *ep = entity_to_idx;
for(size_t n = 0; n < entities.size(); n++)
diff --git a/include/boost/afio/v2.0/config.hpp b/include/boost/afio/v2.0/config.hpp
index e439a27d..9fcf46d1 100644
--- a/include/boost/afio/v2.0/config.hpp
+++ b/include/boost/afio/v2.0/config.hpp
@@ -412,13 +412,11 @@ using BOOSTLITE_NAMESPACE::scoped_undo::undoer;
BOOST_AFIO_V2_NAMESPACE_END
-#if !BOOST_AFIO_HAVE_CXX17_SPAN_IMPLEMENTATION
-#include "../gsl-lite/include/gsl.h"
+// Bring in a span implementation
+#include "../boost-lite/include/span.hpp"
BOOST_AFIO_V2_NAMESPACE_BEGIN
-template <class T> using span = gsl::span<T>;
-using gsl::as_span;
+using namespace boost_lite::span;
BOOST_AFIO_V2_NAMESPACE_END
-#endif
#if BOOST_AFIO_LOGGING_LEVEL
diff --git a/include/boost/afio/v2.0/detail/impl/windows/utils.ipp b/include/boost/afio/v2.0/detail/impl/windows/utils.ipp
index b740f65f..4fb71327 100644
--- a/include/boost/afio/v2.0/detail/impl/windows/utils.ipp
+++ b/include/boost/afio/v2.0/detail/impl/windows/utils.ipp
@@ -142,533 +142,6 @@ namespace utils
}
}
}
-
- namespace fash_hash_detail
- {
- using uint8 = unsigned char;
- using uint32 = unsigned int;
- using uint64 = unsigned long long;
- static constexpr bool ALLOW_UNALIGNED_READS = true;
-
- static BOOST_FORCEINLINE uint64 Rot64(uint64 x, int k) { return (x << k) | (x >> (64 - k)); }
- static BOOST_FORCEINLINE void Mix(const uint64 *data, uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3, uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7, uint64 &s8, uint64 &s9, uint64 &s10, uint64 &s11)
- {
- s0 += data[0];
- s2 ^= s10;
- s11 ^= s0;
- s0 = Rot64(s0, 11);
- s11 += s1;
- s1 += data[1];
- s3 ^= s11;
- s0 ^= s1;
- s1 = Rot64(s1, 32);
- s0 += s2;
- s2 += data[2];
- s4 ^= s0;
- s1 ^= s2;
- s2 = Rot64(s2, 43);
- s1 += s3;
- s3 += data[3];
- s5 ^= s1;
- s2 ^= s3;
- s3 = Rot64(s3, 31);
- s2 += s4;
- s4 += data[4];
- s6 ^= s2;
- s3 ^= s4;
- s4 = Rot64(s4, 17);
- s3 += s5;
- s5 += data[5];
- s7 ^= s3;
- s4 ^= s5;
- s5 = Rot64(s5, 28);
- s4 += s6;
- s6 += data[6];
- s8 ^= s4;
- s5 ^= s6;
- s6 = Rot64(s6, 39);
- s5 += s7;
- s7 += data[7];
- s9 ^= s5;
- s6 ^= s7;
- s7 = Rot64(s7, 57);
- s6 += s8;
- s8 += data[8];
- s10 ^= s6;
- s7 ^= s8;
- s8 = Rot64(s8, 55);
- s7 += s9;
- s9 += data[9];
- s11 ^= s7;
- s8 ^= s9;
- s9 = Rot64(s9, 54);
- s8 += s10;
- s10 += data[10];
- s0 ^= s8;
- s9 ^= s10;
- s10 = Rot64(s10, 22);
- s9 += s11;
- s11 += data[11];
- s1 ^= s9;
- s10 ^= s11;
- s11 = Rot64(s11, 46);
- s10 += s0;
- }
- static BOOST_FORCEINLINE void EndPartial(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, uint64 &h8, uint64 &h9, uint64 &h10, uint64 &h11)
- {
- h11 += h1;
- h2 ^= h11;
- h1 = Rot64(h1, 44);
- h0 += h2;
- h3 ^= h0;
- h2 = Rot64(h2, 15);
- h1 += h3;
- h4 ^= h1;
- h3 = Rot64(h3, 34);
- h2 += h4;
- h5 ^= h2;
- h4 = Rot64(h4, 21);
- h3 += h5;
- h6 ^= h3;
- h5 = Rot64(h5, 38);
- h4 += h6;
- h7 ^= h4;
- h6 = Rot64(h6, 33);
- h5 += h7;
- h8 ^= h5;
- h7 = Rot64(h7, 10);
- h6 += h8;
- h9 ^= h6;
- h8 = Rot64(h8, 13);
- h7 += h9;
- h10 ^= h7;
- h9 = Rot64(h9, 38);
- h8 += h10;
- h11 ^= h8;
- h10 = Rot64(h10, 53);
- h9 += h11;
- h0 ^= h9;
- h11 = Rot64(h11, 42);
- h10 += h0;
- h1 ^= h10;
- h0 = Rot64(h0, 54);
- }
-
- static BOOST_FORCEINLINE void End(const uint64 *data, uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, uint64 &h8, uint64 &h9, uint64 &h10, uint64 &h11)
- {
- h0 += data[0];
- h1 += data[1];
- h2 += data[2];
- h3 += data[3];
- h4 += data[4];
- h5 += data[5];
- h6 += data[6];
- h7 += data[7];
- h8 += data[8];
- h9 += data[9];
- h10 += data[10];
- h11 += data[11];
- EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- }
-
- static BOOST_FORCEINLINE void ShortMix(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3)
- {
- h2 = Rot64(h2, 50);
- h2 += h3;
- h0 ^= h2;
- h3 = Rot64(h3, 52);
- h3 += h0;
- h1 ^= h3;
- h0 = Rot64(h0, 30);
- h0 += h1;
- h2 ^= h0;
- h1 = Rot64(h1, 41);
- h1 += h2;
- h3 ^= h1;
- h2 = Rot64(h2, 54);
- h2 += h3;
- h0 ^= h2;
- h3 = Rot64(h3, 48);
- h3 += h0;
- h1 ^= h3;
- h0 = Rot64(h0, 38);
- h0 += h1;
- h2 ^= h0;
- h1 = Rot64(h1, 37);
- h1 += h2;
- h3 ^= h1;
- h2 = Rot64(h2, 62);
- h2 += h3;
- h0 ^= h2;
- h3 = Rot64(h3, 34);
- h3 += h0;
- h1 ^= h3;
- h0 = Rot64(h0, 5);
- h0 += h1;
- h2 ^= h0;
- h1 = Rot64(h1, 36);
- h1 += h2;
- h3 ^= h1;
- }
-
- static BOOST_FORCEINLINE void ShortEnd(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3)
- {
- h3 ^= h2;
- h2 = Rot64(h2, 15);
- h3 += h2;
- h0 ^= h3;
- h3 = Rot64(h3, 52);
- h0 += h3;
- h1 ^= h0;
- h0 = Rot64(h0, 26);
- h1 += h0;
- h2 ^= h1;
- h1 = Rot64(h1, 51);
- h2 += h1;
- h3 ^= h2;
- h2 = Rot64(h2, 28);
- h3 += h2;
- h0 ^= h3;
- h3 = Rot64(h3, 9);
- h0 += h3;
- h1 ^= h0;
- h0 = Rot64(h0, 47);
- h1 += h0;
- h2 ^= h1;
- h1 = Rot64(h1, 54);
- h2 += h1;
- h3 ^= h2;
- h2 = Rot64(h2, 32);
- h3 += h2;
- h0 ^= h3;
- h3 = Rot64(h3, 25);
- h0 += h3;
- h1 ^= h0;
- h0 = Rot64(h0, 63);
- h1 += h0;
- }
- }
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4127) // use of ALLOW_UNALIGNED_READS
-#endif
-
- void fast_hash::short_(uint128 &hash, const void *message, size_t length) noexcept
- {
- using namespace fash_hash_detail;
- uint64 buf[2 * sc_numVars];
- union {
- const uint8 *p8;
- uint32 *p32;
- uint64 *p64;
- size_t i;
- } u;
-
- u.p8 = (const uint8 *) message;
-
- if(!ALLOW_UNALIGNED_READS && (u.i & 0x7))
- {
- memcpy(buf, message, length);
- u.p64 = buf;
- }
-
- size_t remainder = length % 32;
- uint64 a = hash.as_longlongs[0];
- uint64 b = hash.as_longlongs[1];
- uint64 c = sc_const;
- uint64 d = sc_const;
-
- if(length > 15)
- {
- const uint64 *end = u.p64 + (length / 32) * 4;
-
- // handle all complete sets of 32 bytes
- for(; u.p64 < end; u.p64 += 4)
- {
- c += u.p64[0];
- d += u.p64[1];
- ShortMix(a, b, c, d);
- a += u.p64[2];
- b += u.p64[3];
- }
-
- // Handle the case of 16+ remaining bytes.
- if(remainder >= 16)
- {
- c += u.p64[0];
- d += u.p64[1];
- ShortMix(a, b, c, d);
- u.p64 += 2;
- remainder -= 16;
- }
- }
-
- // Handle the last 0..15 bytes, and its length
- d += ((uint64) length) << 56;
- switch(remainder)
- {
- case 15:
- d += ((uint64) u.p8[14]) << 48;
- case 14:
- d += ((uint64) u.p8[13]) << 40;
- case 13:
- d += ((uint64) u.p8[12]) << 32;
- case 12:
- d += u.p32[2];
- c += u.p64[0];
- break;
- case 11:
- d += ((uint64) u.p8[10]) << 16;
- case 10:
- d += ((uint64) u.p8[9]) << 8;
- case 9:
- d += (uint64) u.p8[8];
- case 8:
- c += u.p64[0];
- break;
- case 7:
- c += ((uint64) u.p8[6]) << 48;
- case 6:
- c += ((uint64) u.p8[5]) << 40;
- case 5:
- c += ((uint64) u.p8[4]) << 32;
- case 4:
- c += u.p32[0];
- break;
- case 3:
- c += ((uint64) u.p8[2]) << 16;
- case 2:
- c += ((uint64) u.p8[1]) << 8;
- case 1:
- c += (uint64) u.p8[0];
- break;
- case 0:
- c += sc_const;
- d += sc_const;
- }
- ShortEnd(a, b, c, d);
- hash.as_longlongs[0] = a;
- hash.as_longlongs[1] = b;
- }
-
- void fast_hash::add(const char *message, size_t length) noexcept
- {
- using namespace fash_hash_detail;
- uint64 h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11;
- size_t newLength = length + m_remainder;
- uint8 remainder;
- union {
- const uint8 *p8;
- uint64 *p64;
- size_t i;
- } u;
- const uint64 *end;
-
- // Is this message fragment too short? If it is, stuff it away.
- if(newLength < sc_bufSize)
- {
- memcpy(&((uint8 *) m_data)[m_remainder], message, length);
- m_length = length + m_length;
- m_remainder = (uint8) newLength;
- return;
- }
-
- // init the variables
- if(m_length < sc_bufSize)
- {
- h0 = h3 = h6 = h9 = m_state[0];
- h1 = h4 = h7 = h10 = m_state[1];
- h2 = h5 = h8 = h11 = sc_const;
- }
- else
- {
- h0 = m_state[0];
- h1 = m_state[1];
- h2 = m_state[2];
- h3 = m_state[3];
- h4 = m_state[4];
- h5 = m_state[5];
- h6 = m_state[6];
- h7 = m_state[7];
- h8 = m_state[8];
- h9 = m_state[9];
- h10 = m_state[10];
- h11 = m_state[11];
- }
- m_length = length + m_length;
-
- // if we've got anything stuffed away, use it now
- if(m_remainder)
- {
- uint8 prefix = sc_bufSize - m_remainder;
- memcpy(&(((uint8 *) m_data)[m_remainder]), message, prefix);
- u.p64 = m_data;
- Mix(u.p64, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- Mix(&u.p64[sc_numVars], h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- u.p8 = ((const uint8 *) message) + prefix;
- length -= prefix;
- }
- else
- {
- u.p8 = (const uint8 *) message;
- }
-
- // handle all whole blocks of sc_blockSize bytes
- end = u.p64 + (length / sc_blockSize) * sc_numVars;
- remainder = (uint8)(length - ((const uint8 *) end - u.p8));
- if(ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0)
- {
- while(u.p64 < end)
- {
- Mix(u.p64, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- u.p64 += sc_numVars;
- }
- }
- else
- {
- while(u.p64 < end)
- {
- memcpy(m_data, u.p8, sc_blockSize);
- Mix(m_data, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- u.p64 += sc_numVars;
- }
- }
-
- // stuff away the last few bytes
- m_remainder = remainder;
- memcpy(m_data, end, remainder);
-
- // stuff away the variables
- m_state[0] = h0;
- m_state[1] = h1;
- m_state[2] = h2;
- m_state[3] = h3;
- m_state[4] = h4;
- m_state[5] = h5;
- m_state[6] = h6;
- m_state[7] = h7;
- m_state[8] = h8;
- m_state[9] = h9;
- m_state[10] = h10;
- m_state[11] = h11;
- }
-
- uint128 fast_hash::finalise() noexcept
- {
- using namespace fash_hash_detail;
- uint128 ret;
- // init the variables
- if(m_length < sc_bufSize)
- {
- ret.as_longlongs[0] = m_state[0];
- ret.as_longlongs[1] = m_state[1];
- short_(ret, m_data, m_length);
- return ret;
- }
-
- const uint64 *data = (const uint64 *) m_data;
- uint8 remainder = m_remainder;
-
- uint64 h0 = m_state[0];
- uint64 h1 = m_state[1];
- uint64 h2 = m_state[2];
- uint64 h3 = m_state[3];
- uint64 h4 = m_state[4];
- uint64 h5 = m_state[5];
- uint64 h6 = m_state[6];
- uint64 h7 = m_state[7];
- uint64 h8 = m_state[8];
- uint64 h9 = m_state[9];
- uint64 h10 = m_state[10];
- uint64 h11 = m_state[11];
-
- if(remainder >= sc_blockSize)
- {
- // m_data can contain two blocks; handle any whole first block
- Mix(data, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- data += sc_numVars;
- remainder -= sc_blockSize;
- }
-
- // mix in the last partial block, and the length mod sc_blockSize
- memset(&((uint8 *) data)[remainder], 0, (sc_blockSize - remainder));
-
- ((uint8 *) data)[sc_blockSize - 1] = remainder;
-
- // do some final mixing
- End(data, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
-
- ret.as_longlongs[0] = h0;
- ret.as_longlongs[1] = h1;
- return ret;
- }
-
- uint128 fast_hash::hash(const char *message, size_t length, const uint128 &_ret) noexcept
- {
- uint128 ret(_ret);
- using namespace fash_hash_detail;
- if(length < sc_bufSize)
- {
- short_(ret, message, length);
- return ret;
- }
-
- uint64 h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11;
- uint64 buf[sc_numVars];
- uint64 *end;
- union {
- const uint8 *p8;
- uint64 *p64;
- size_t i;
- } u;
- size_t remainder;
-
- h0 = h3 = h6 = h9 = ret.as_longlongs[0];
- h1 = h4 = h7 = h10 = ret.as_longlongs[1];
- h2 = h5 = h8 = h11 = sc_const;
-
- u.p8 = (const uint8 *) message;
- end = u.p64 + (length / sc_blockSize) * sc_numVars;
-
- // handle all whole sc_blockSize blocks of bytes
- if(ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0))
- {
- while(u.p64 < end)
- {
- Mix(u.p64, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- u.p64 += sc_numVars;
- }
- }
- else
- {
- while(u.p64 < end)
- {
- memcpy(buf, u.p64, sc_blockSize);
- Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
- u.p64 += sc_numVars;
- }
- }
-
- // handle the last partial block of sc_blockSize bytes
- remainder = (length - ((const uint8 *) end - (const uint8 *) message));
- memcpy(buf, end, remainder);
- memset(((uint8 *) buf) + remainder, 0, sc_blockSize - remainder);
- ((uint8 *) buf)[sc_blockSize - 1] = (uint8) remainder;
-
- // do some final mixing
- End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
-
- ret.as_longlongs[0] = h0;
- ret.as_longlongs[1] = h1;
- return ret;
- }
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
}
BOOST_AFIO_V2_NAMESPACE_END
diff --git a/include/boost/afio/v2.0/utils.hpp b/include/boost/afio/v2.0/utils.hpp
index 8ff7ab02..cc482e14 100644
--- a/include/boost/afio/v2.0/utils.hpp
+++ b/include/boost/afio/v2.0/utils.hpp
@@ -37,6 +37,8 @@ DEALINGS IN THE SOFTWARE.
#endif
#include "config.hpp"
+#include "../boost-lite/include/algorithm/string.hpp"
+
//! \file utils.hpp Provides namespace utils
BOOST_AFIO_V2_NAMESPACE_EXPORT_BEGIN
@@ -124,121 +126,6 @@ namespace utils
*/
BOOST_AFIO_HEADERS_ONLY_FUNC_SPEC void random_fill(char *buffer, size_t bytes);
-/*! \brief Converts a number to a hex string. Out buffer can be same as in buffer.
-
-Note that the character range used is a 16 item table of:
-
-0123456789abcdef
-
-This lets one pack one byte of input into two bytes of output.
-
-\ingroup utils
-\complexity{O(N) where N is the length of the number.}
-\exceptionmodel{Throws exception if output buffer is too small for input.}
-*/
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 6293) // MSVC sanitiser warns that we wrap n in the for loop
-#endif
- inline size_t to_hex_string(char *out, size_t outlen, const char *_in, size_t inlen)
- {
- unsigned const char *in = (unsigned const char *) _in;
- static constexpr char table[] = "0123456789abcdef";
- if(outlen < inlen * 2)
- throw std::invalid_argument("Output buffer too small.");
- for(size_t n = inlen - 2; n <= inlen - 2; n -= 2)
- {
- out[n * 2 + 3] = table[(in[n + 1] >> 4) & 0xf];
- out[n * 2 + 2] = table[in[n + 1] & 0xf];
- out[n * 2 + 1] = table[(in[n] >> 4) & 0xf];
- out[n * 2 + 0] = table[in[n] & 0xf];
- }
- if(inlen & 1)
- {
- out[1] = table[(in[0] >> 4) & 0xf];
- out[0] = table[in[0] & 0xf];
- }
- return inlen * 2;
- }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- //! \overload
- inline size_t to_hex_string(span<char> out, const span<char> in) { return to_hex_string(out.data(), out.size(), in.data(), in.size()); }
- //! \overload
- inline std::string to_hex_string(span<char> in)
- {
- std::string out(in.size() * 2, ' ');
- to_hex_string(const_cast<char *>(out.data()), out.size(), in.data(), in.size());
- return out;
- }
-
- /*! \brief Converts a hex string to a number. Out buffer can be same as in buffer.
-
- Note that this routine is about 43% slower than to_hex_string(), half of which is due to input validation.
-
- \ingroup utils
- \complexity{O(N) where N is the length of the string.}
- \exceptionmodel{Throws exception if output buffer is too small for input or input size is not multiple of two.}
- */
- inline size_t from_hex_string(char *out, size_t outlen, const char *in, size_t inlen)
- {
- if(inlen % 2)
- throw std::invalid_argument("Input buffer not multiple of two.");
- if(outlen < inlen / 2)
- throw std::invalid_argument("Output buffer too small.");
- bool is_invalid = false;
- auto fromhex = [&is_invalid](char c) -> unsigned char {
-#if 1
- // ASCII starting from 48 is 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
- // 48 65 97
- static constexpr unsigned char table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // +10 = 58
- 255, 255, 255, 255, 255, 255, 255, // +7 = 65
- 10, 11, 12, 13, 14, 15, // +6 = 71
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // +26 = 97
- 10, 11, 12, 13, 14, 15};
- unsigned char r = 255;
- if(c >= 48 && c <= 102)
- r = table[c - 48];
- if(r == 255)
- is_invalid = true;
- return r;
-#else
- if(c >= '0' && c <= '9')
- return c - '0';
- if(c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- if(c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- BOOST_AFIO_THROW(std::invalid_argument("Input is not hexadecimal."));
-#endif
- };
- for(size_t n = 0; n < inlen / 2; n += 4)
- {
- unsigned char c[8];
- c[0] = fromhex(in[n * 2]);
- c[1] = fromhex(in[n * 2 + 1]);
- c[2] = fromhex(in[n * 2 + 2]);
- c[3] = fromhex(in[n * 2 + 3]);
- out[n] = (c[1] << 4) | c[0];
- c[4] = fromhex(in[n * 2 + 4]);
- c[5] = fromhex(in[n * 2 + 5]);
- out[n + 1] = (c[3] << 4) | c[2];
- c[6] = fromhex(in[n * 2 + 6]);
- c[7] = fromhex(in[n * 2 + 7]);
- out[n + 2] = (c[5] << 4) | c[4];
- out[n + 3] = (c[7] << 4) | c[6];
- }
- for(size_t n = inlen / 2 - (inlen / 2) % 4; n < inlen / 2; n++)
- {
- unsigned char c1 = fromhex(in[n * 2]), c2 = fromhex(in[n * 2 + 1]);
- out[n] = (c2 << 4) | c1;
- }
- if(is_invalid)
- throw std::invalid_argument("Input is not hexadecimal.");
- return inlen / 2;
- }
-
/*! \brief Returns a cryptographically random string capable of being used as a filename. Essentially random_fill() + to_hex_string().
\param randomlen The number of bytes of randomness to use for the string.
@@ -252,275 +139,10 @@ This lets one pack one byte of input into two bytes of output.
size_t outlen = randomlen * 2;
std::string ret(outlen, 0);
random_fill(const_cast<char *>(ret.data()), randomlen);
- to_hex_string(const_cast<char *>(ret.data()), outlen, ret.data(), randomlen);
+ boost_lite::algorithm::string::to_hex_string(const_cast<char *>(ret.data()), outlen, ret.data(), randomlen);
return ret;
}
-#ifndef BOOST_AFIO_SECDEC_INTRINSICS
-#if defined(__GCC__) || defined(__clang__)
-#define BOOST_AFIO_SECDEC_INTRINSICS 1
-#elif defined(_MSC_VER) && (defined(_M_X64) || _M_IX86_FP == 1)
-#define BOOST_AFIO_SECDEC_INTRINSICS 1
-#endif
-#endif
-#ifndef BOOST_AFIO_SECDEC_INTRINSICS
-#define BOOST_AFIO_SECDEC_INTRINSICS 0
-#endif
- /*! \class secded_ecc
- \brief Calculates the single error correcting double error detecting (SECDED) Hamming Error Correcting Code for a \em blocksize block of bytes. For example, a secdec_ecc<8> would be the very common 72,64 Hamming code used in ECC RAM, or secdec_ecc<4096> would be for a 32784,32768 Hamming code.
-
- Did you know that some non-ECC RAM systems can see 1e-12 flips/bit/hour, which is 3.3 bits flipped in a 16Gb RAM system
- per 24 hours). See Schroeder, Pinheiro and Weber (2009) 'DRAM Errors in the Wild: A Large-Scale Field Study'.
-
- After construction during which lookup tables are built, no state is modified and therefore this class is safe for static
- storage (indeed if C++ 14 is available, the constructor is constexpr). The maximum number of bits in a code is a good four
- billion, I did try limiting it to 65536 for performance but it wasn't worth it, and one might want > 8Kb blocks maybe.
- As with all SECDED ECC, undefined behaviour occurs when more than two bits of error are present or the ECC supplied
- is incorrect. You should combine this SECDED with a robust hash which can tell you definitively if a buffer is error
- free or not rather than relying on this to correctly do so.
-
- The main intended use case for this routine is calculating the ECC on data being written to disc, and hence that is
- where performance has been maximised. It is not expected that this routine will be frequently called on data being read
- from disc i.e. only when its hash doesn't match its contents which should be very rare, and then a single bit heal using this routine is attempted
- before trying again with the hash. Care was taken that really enormous SECDEDs are fast, in fact tuning was mostly
- done for the 32784,32768 code which can heal one bad bit per 4Kb page as the main thing we have in mind is achieving
- reliable filing system code on computers without ECC RAM and in which sustained large quantities of random disc i/o produce
- a worrying number of flipped bits in a 24 hour period (anywhere between 0 and 3 on my hardware here, average is about 0.8).
-
- Performance of the fixed block size routine where you supply whole chunks of \em blocksize is therefore \b particularly excellent
- as I spent a lot of time tuning it for Ivy Bridge and later out of order architectures: an
- amazing 22 cycles per byte for the 32784,32768 code, which is a testament to modern out of order CPUs (remember SECDED inherently must work a bit
- at a time, so that's just 2.75 amortised CPU cycles per bit which includes a table load, a bit test, and a conditional XOR)
- i.e. it's pushing about 1.5 ops per clock cycle. On my 3.9Ghz i7-3770K here, I see about 170Mb/sec per CPU core.
-
- The variable length routine is necessarily much slower as it must work in single bytes, and achieves 72 cycles per byte,
- or 9 cycles per bit (64Mb/sec per CPU core).
-
- \ingroup utils
- \complexity{O(N) where N is the blocksize}
- \exceptionmodel{Throws constexpr exceptions in constructor only, otherwise entirely noexcept.}
- */
- template <size_t blocksize> class secded_ecc
- {
- public:
- typedef unsigned int result_type; //!< The largest ECC which can be calculated
- private:
- static constexpr size_t bits_per_byte = 8;
- typedef unsigned char unit_type; // The batch unit of processing
- result_type bitsvalid;
- // Many CPUs (x86) are slow doing variable bit shifts, so keep a table
- result_type ecc_twospowers[sizeof(result_type) * bits_per_byte];
- unsigned short ecc_table[blocksize * bits_per_byte];
- static bool _is_single_bit_set(result_type x)
- {
-#ifndef _MSC_VER
-#if defined(__i386__) || defined(__x86_64__)
-#ifndef __SSE4_2__
- // Do a once off runtime check
- static int have_popcnt = [] {
- size_t cx, dx;
-#if defined(__x86_64__)
- asm("cpuid" : "=c"(cx), "=d"(dx) : "a"(1), "b"(0), "c"(0), "d"(0));
-#else
- asm("pushl %%ebx\n\tcpuid\n\tpopl %%ebx\n\t" : "=c"(cx), "=d"(dx) : "a"(1), "c"(0), "d"(0));
-#endif
- return (dx & (1 << 26)) != 0 /*SSE2*/ && (cx & (1 << 23)) != 0 /*POPCNT*/;
- }();
- if(have_popcnt)
-#endif
- {
- unsigned count;
- asm("popcnt %1,%0" : "=r"(count) : "rm"(x) : "cc");
- return count == 1;
- }
-#endif
- return __builtin_popcount(x) == 1;
-#else
- x -= (x >> 1) & 0x55555555;
- x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
- x = (x + (x >> 4)) & 0x0f0f0f0f;
- unsigned int count = (x * 0x01010101) >> 24;
- return count == 1;
-#if 0
- x -= (x >> 1) & 0x5555555555555555ULL;
- x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);
- x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
- unsigned long long count = (x * 0x0101010101010101ULL) >> 56;
- return count == 1;
-#endif
-#endif
- }
-
- public:
- //! Constructs an instance, configuring the necessary lookup tables
- BOOST_CXX14_CONSTEXPR secded_ecc()
- {
- for(size_t n = 0; n < sizeof(result_type) * bits_per_byte; n++)
- ecc_twospowers[n] = ((result_type) 1 << n);
- result_type length = blocksize * bits_per_byte;
- // This is (data bits + parity bits + 1) <= 2^(parity bits)
- for(result_type p = 1; p < sizeof(result_type) * bits_per_byte; p++)
- if((length + p + 1) <= ecc_twospowers[p])
- {
- bitsvalid = p;
- break;
- }
- if((bits_per_byte - 1 + bitsvalid) / bits_per_byte > sizeof(result_type))
- throw std::runtime_error("secdec_ecc: ECC would exceed the size of result_type!");
- for(result_type i = 0; i < blocksize * bits_per_byte; i++)
- {
- // Make a code bit
- result_type b = i + 1;
-#if BOOST_AFIO_SECDEC_INTRINSICS && 0 // let constexpr do its thing
-#ifdef _MSC_VER
- unsigned long _topbit;
- _BitScanReverse(&_topbit, b);
- result_type topbit = _topbit;
-#else
- result_type topbit = bits_per_byte * sizeof(result_type) - __builtin_clz(b);
-#endif
- b += topbit;
- if(b >= ecc_twospowers[topbit])
- b++;
-// while(b>ecc_twospowers(_topbit+1)) _topbit++;
-// b+=_topbit;
-// if(b>=ecc_twospowers(_topbit)) b++;
-#else
- for(size_t p = 0; ecc_twospowers[p] < (b + 1); p++)
- b++;
-#endif
- ecc_table[i] = (unsigned short) b;
- if(b > (unsigned short) -1)
- throw std::runtime_error("secdec_ecc: Precalculated table has exceeded its bounds");
- }
- }
- //! The number of bits valid in result_type
- constexpr result_type result_bits_valid() const noexcept { return bitsvalid; }
- //! Accumulate ECC from fixed size buffer
- result_type operator()(result_type ecc, const char *buffer) const noexcept
- {
- if(blocksize < sizeof(unit_type) * 8)
- return (*this)(ecc, buffer, blocksize);
- // Process in lumps of eight
- const unit_type *_buffer = (const unit_type *) buffer;
- //#pragma omp parallel for reduction(^:ecc)
- for(size_t i = 0; i < blocksize; i += sizeof(unit_type) * 8)
- {
- union {
- unsigned long long v;
- unit_type c[8];
- };
- result_type prefetch[8];
- v = *(unsigned long long *) (&_buffer[0 + i / sizeof(unit_type)]); // min 1 cycle
-#define BOOST_AFIO_ROUND(n) \
- prefetch[0] = ecc_table[(i + 0) * 8 + n]; \
- prefetch[1] = ecc_table[(i + 1) * 8 + n]; \
- prefetch[2] = ecc_table[(i + 2) * 8 + n]; \
- prefetch[3] = ecc_table[(i + 3) * 8 + n]; \
- prefetch[4] = ecc_table[(i + 4) * 8 + n]; \
- prefetch[5] = ecc_table[(i + 5) * 8 + n]; \
- prefetch[6] = ecc_table[(i + 6) * 8 + n]; \
- prefetch[7] = ecc_table[(i + 7) * 8 + n]; \
- if(c[0] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[0]; \
- if(c[1] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[1]; \
- if(c[2] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[2]; \
- if(c[3] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[3]; \
- if(c[4] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[4]; \
- if(c[5] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[5]; \
- if(c[6] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[6]; \
- if(c[7] & ((unit_type) 1 << n)) \
- ecc ^= prefetch[7];
- BOOST_AFIO_ROUND(0) // prefetch = min 8, bit test and xor = min 16, total = 24
- BOOST_AFIO_ROUND(1)
- BOOST_AFIO_ROUND(2)
- BOOST_AFIO_ROUND(3)
- BOOST_AFIO_ROUND(4)
- BOOST_AFIO_ROUND(5)
- BOOST_AFIO_ROUND(6)
- BOOST_AFIO_ROUND(7)
-#undef BOOST_AFIO_ROUND // total should be 1+(8*24/3)=65
- }
- return ecc;
- }
- result_type operator()(const char *buffer) const noexcept { return (*this)(0, buffer); }
- //! Accumulate ECC from partial buffer where \em length <= \em blocksize
- result_type operator()(result_type ecc, const char *buffer, size_t length) const noexcept
- {
- const unit_type *_buffer = (const unit_type *) buffer;
- //#pragma omp parallel for reduction(^:ecc)
- for(size_t i = 0; i < length; i += sizeof(unit_type))
- {
- unit_type c = _buffer[i / sizeof(unit_type)]; // min 1 cycle
- if(!c) // min 1 cycle
- continue;
- char bitset[bits_per_byte * sizeof(unit_type)];
- result_type prefetch[bits_per_byte * sizeof(unit_type)];
- // Most compilers will roll this out
- for(size_t n = 0; n < bits_per_byte * sizeof(unit_type); n++) // min 16 cycles
- {
- bitset[n] = !!(c & ((unit_type) 1 << n));
- prefetch[n] = ecc_table[i * bits_per_byte + n]; // min 8 cycles
- }
- result_type localecc = 0;
- for(size_t n = 0; n < bits_per_byte * sizeof(unit_type); n++)
- {
- if(bitset[n]) // min 8 cycles
- localecc ^= prefetch[n]; // min 8 cycles
- }
- ecc ^= localecc; // min 1 cycle. Total cycles = min 43 cycles/byte
- }
- return ecc;
- }
- result_type operator()(const char *buffer, size_t length) const noexcept { return (*this)(0, buffer, length); }
- //! Given the original ECC and the new ECC for a buffer, find the bad bit. Return (result_type)-1 if not found (e.g. ECC corrupt)
- result_type find_bad_bit(result_type good_ecc, result_type bad_ecc) const noexcept
- {
- result_type length = blocksize * bits_per_byte, eccdiff = good_ecc ^ bad_ecc;
- if(_is_single_bit_set(eccdiff))
- return (result_type) -1;
- for(result_type i = 0, b = 1; i < length; i++, b++)
- {
- // Skip parity bits
- while(_is_single_bit_set(b))
- b++;
- if(b == eccdiff)
- return i;
- }
- return (result_type) -1;
- }
- //! The outcomes from verify()
- enum verify_status
- {
- corrupt = 0, //!< The buffer had more than a single bit corrupted or the ECC was invalid
- okay = 1, //!< The buffer had no errors
- healed = 2 //!< The buffer was healed
- };
- //! Verifies and heals when possible a buffer, returning non zero if the buffer is error free
- verify_status verify(char *buffer, result_type good_ecc) const noexcept
- {
- result_type this_ecc = (*this)(0, buffer);
- if(this_ecc == good_ecc)
- return verify_status::okay; // no errors
- result_type badbit = find_bad_bit(good_ecc, this_ecc);
- if((result_type) -1 == badbit)
- return verify_status::corrupt; // parity corrupt?
- buffer[badbit / bits_per_byte] ^= (unsigned char) ecc_twospowers[badbit % bits_per_byte];
- this_ecc = (*this)(0, buffer);
- if(this_ecc == good_ecc)
- return healed; // error healed
- // Put the bit back
- buffer[badbit / bits_per_byte] ^= (unsigned char) ecc_twospowers[badbit % bits_per_byte];
- return verify_status::corrupt; // more than one bit was corrupt
- }
- };
-
namespace detail
{
struct large_page_allocation
@@ -638,94 +260,6 @@ This lets one pack one byte of input into two bytes of output.
};
};
template <class T, class U> inline bool operator==(const page_allocator<T> &, const page_allocator<U> &) noexcept { return true; }
-
- /*! \union uint128
- \brief An unsigned 128 bit value
- */
- union alignas(16) uint128 {
- unsigned char as_bytes[16];
- unsigned short as_shorts[8];
- unsigned int as_ints[4];
- unsigned long long as_longlongs[2];
-#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
-#if defined(__x86_64__) || defined(_M_X64) || defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
- // Strongly hint to the compiler what to do here
- __m128i as_m128i;
-#endif
-#endif
- //! Default constructor, no bits set
- uint128() noexcept {}
- //! All bits zero constructor
- constexpr uint128(std::nullptr_t) noexcept : as_longlongs{0, 0} {}
- private:
- static const uint128 &_allbitszero()
- {
- static uint128 v(nullptr);
- return v;
- }
-
- public:
- explicit operator bool() const noexcept { return (*this) != _allbitszero(); }
- bool operator!() const noexcept { return (*this) == _allbitszero(); }
- bool operator==(const uint128 &o) const noexcept { return as_longlongs[1] == o.as_longlongs[1] && as_longlongs[0] == o.as_longlongs[0]; }
- bool operator!=(const uint128 &o) const noexcept { return as_longlongs[1] != o.as_longlongs[1] || as_longlongs[0] != o.as_longlongs[0]; }
- bool operator<(const uint128 &o) const noexcept { return as_longlongs[0] < o.as_longlongs[0] || (as_longlongs[0] == o.as_longlongs[0] && as_longlongs[1] < o.as_longlongs[1]); }
- bool operator<=(const uint128 &o) const noexcept { return as_longlongs[0] < o.as_longlongs[0] || (as_longlongs[0] == o.as_longlongs[0] && as_longlongs[1] <= o.as_longlongs[1]); }
- bool operator>(const uint128 &o) const noexcept { return as_longlongs[0] > o.as_longlongs[0] || (as_longlongs[0] == o.as_longlongs[0] && as_longlongs[1] > o.as_longlongs[1]); }
- bool operator>=(const uint128 &o) const noexcept { return as_longlongs[0] > o.as_longlongs[0] || (as_longlongs[0] == o.as_longlongs[0] && as_longlongs[1] >= o.as_longlongs[1]); }
- };
- static_assert(sizeof(uint128) == 16, "uint128 is not 16 bytes long!");
- static_assert(alignof(uint128) == 16, "uint128 is not aligned to 16 byte multiples!");
-
- /*! \class fast_hash
- \brief Fast very collision resistant uint128 hash. Currently SpookyHash @ 0.3 cycles/byte.
- */
- class BOOST_AFIO_DECL fast_hash
- {
- using uint8 = unsigned char;
- using uint64 = unsigned long long;
-
- // number of uint64's in internal state
- static constexpr size_t sc_numVars = 12;
-
- // size of the internal state
- static constexpr size_t sc_blockSize = sc_numVars * 8;
-
- // size of buffer of unhashed data, in bytes
- static constexpr size_t sc_bufSize = 2 * sc_blockSize;
-
- //
- // sc_const: a constant which:
- // * is not zero
- // * is odd
- // * is a not-very-regular mix of 1's and 0's
- // * does not need any other special mathematical properties
- //
- static constexpr uint64 sc_const = 0xdeadbeefdeadbeefULL;
-
- uint64 m_data[2 * sc_numVars]; // unhashed data, for partial messages
- uint64 m_state[sc_numVars]; // internal state of the hash
- size_t m_length; // total length of the input so far
- uint8 m_remainder; // length of unhashed data stashed in m_data
-
- static void short_(uint128 &hash, const void *data, size_t bytes) noexcept;
-
- public:
- //! Initialise the hash with an optional seed
- constexpr fast_hash(const uint128 &seed = uint128(nullptr)) noexcept : m_data{0}, m_state{seed.as_longlongs[0], seed.as_longlongs[1]}, m_length(0), m_remainder(0) {}
-
- //! Hash input
- void add(const char *data, size_t bytes) noexcept;
-
- //! Finalise and return hash
- uint128 finalise() noexcept;
-
- //! Single shot hash of a sequence of bytes
- static uint128 hash(const char *data, size_t bytes, const uint128 &seed = uint128(nullptr)) noexcept;
-
- //! Single shot hash of a span
- template <typename T> static uint128 hash(const span<T> &str) noexcept { return hash((char *) str.data(), str.size() * sizeof(T)); }
- };
}
BOOST_AFIO_V2_NAMESPACE_END
diff --git a/test/kerneltest b/test/kerneltest
-Subproject 7a6d486f020c61534b1187942648641e1b1b9c2
+Subproject c6e0e8b75a2558ba56d632da9b6c8fef16c8ad7
diff --git a/test/tests/shared_fs_mutex.cpp b/test/tests/shared_fs_mutex.cpp
index 87596fbf..174e06e1 100644
--- a/test/tests/shared_fs_mutex.cpp
+++ b/test/tests/shared_fs_mutex.cpp
@@ -8,6 +8,11 @@ File Created: Aug 2016
#include "../../include/boost/afio/afio.hpp"
#include "../kerneltest/include/boost/kerneltest.hpp"
+BOOST_KERNELTEST_TEST_KERNEL(unit, afio, shared_fs_mutex, entity_endian, "Tests that afio::algorithm::shared_fs_mutex::entity_type has the right endian", [] {
+ BOOST_AFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type v(0, true);
+ BOOST_REQUIRE(v._init != 1UL);
+}())
+
#include <codecvt>
#include <unordered_map>