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--Readme.md2
-rw-r--r--include/afio/revision.hpp6
-rw-r--r--include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp2
-rw-r--r--include/afio/v2.0/config.hpp217
-rw-r--r--include/afio/v2.0/detail/impl/posix/async_file_handle.ipp2
-rw-r--r--include/afio/v2.0/detail/impl/posix/io_handle.ipp2
-rw-r--r--include/afio/v2.0/detail/impl/windows/async_file_handle.ipp2
-rw-r--r--include/afio/v2.0/detail/impl/windows/fs_handle.ipp2
-rw-r--r--include/afio/v2.0/handle.hpp59
-rw-r--r--include/afio/v2.0/io_handle.hpp36
-rw-r--r--include/afio/v2.0/map_handle.hpp18
-rw-r--r--include/afio/v2.0/stat.hpp2
-rw-r--r--include/afio/v2.0/statfs.hpp2
-rw-r--r--test/test_kernel_decl.hpp51
-rw-r--r--test/tests/async_io.cpp5
-rw-r--r--test/tests/coroutines.cpp3
-rw-r--r--test/tests/current_path.cpp3
-rw-r--r--test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp9
-rw-r--r--test/tests/directory_handle_create_close/runner.cpp2
-rw-r--r--test/tests/directory_handle_enumerate/runner.cpp2
-rw-r--r--test/tests/file_handle_create_close/runner.cpp2
-rw-r--r--test/tests/file_handle_lock_unlock.cpp3
-rw-r--r--test/tests/map_handle_create_close/runner.cpp2
-rw-r--r--test/tests/mapped_view.cpp3
-rw-r--r--test/tests/path_discovery.cpp3
-rw-r--r--test/tests/path_view.cpp3
-rw-r--r--test/tests/section_handle_create_close/runner.cpp2
-rw-r--r--test/tests/shared_fs_mutex.cpp3
-rw-r--r--test/tests/trivial_vector.cpp3
29 files changed, 323 insertions, 128 deletions
diff --git a/Readme.md b/Readme.md
index 0ea2bcab..8a4a52d1 100644
--- a/Readme.md
+++ b/Readme.md
@@ -9,7 +9,7 @@ Tarballs of source and prebuilt binaries for Linux x64 and Windows x64:
### Immediate todos in order of priority:
-- [ ] Implement new custom C++ exception synthesis support from Outcome.
+- [x] Implement new custom C++ exception synthesis support from Outcome.
- [ ] Run clang-tidy fix pass, it's got a bit untidy recently.
- [ ] `atomic_append` isn't actually being tested in shared_fs_mutex
- [ ] Implement a non-toy ACID key-value BLOB store and send it to Boost for peer review.
diff --git a/include/afio/revision.hpp b/include/afio/revision.hpp
index ff81a405..73204bcd 100644
--- a/include/afio/revision.hpp
+++ b/include/afio/revision.hpp
@@ -1,4 +1,4 @@
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define AFIO_PREVIOUS_COMMIT_REF 9e315f74277f3bd9ccf7db0d17e6a991b0afbe46
-#define AFIO_PREVIOUS_COMMIT_DATE "2017-11-20 13:39:42 +00:00"
-#define AFIO_PREVIOUS_COMMIT_UNIQUE 9e315f74
+#define AFIO_PREVIOUS_COMMIT_REF e2b51a59d8ae530bdc2af70f785422c084191034
+#define AFIO_PREVIOUS_COMMIT_DATE "2017-11-21 22:22:28 +00:00"
+#define AFIO_PREVIOUS_COMMIT_UNIQUE e2b51a59
diff --git a/include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp b/include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
index 713510a3..eb806fd3 100644
--- a/include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
+++ b/include/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
@@ -154,7 +154,7 @@ namespace algorithm
if(ret.has_error())
{
const auto &ec = ret.error();
- if(ec.category() != std::generic_category() || (ec.value() != EAGAIN && ec.value() != EEXIST))
+ if(ec != std::errc::resource_unavailable_try_again && ec != std::errc::file_exists)
return ret.error();
// Collided with another locker
was_contended = n;
diff --git a/include/afio/v2.0/config.hpp b/include/afio/v2.0/config.hpp
index b1e7430b..3787d9b9 100644
--- a/include/afio/v2.0/config.hpp
+++ b/include/afio/v2.0/config.hpp
@@ -38,11 +38,18 @@ Distributed under the Boost Software License, Version 1.0.
#define AFIO_HEADERS_ONLY 1
#endif
+//! \def AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+//! \brief Define to not record the current handle's path in any failure info.
+
#if !defined(AFIO_LOGGING_LEVEL)
//! \brief How much detail to log. 0=disabled, 1=fatal, 2=error, 3=warn, 4=info, 5=debug, 6=all.
//! Defaults to error level. \ingroup config
+#ifdef NDEBUG
+#define AFIO_LOGGING_LEVEL 1 // fatal
+#else
#define AFIO_LOGGING_LEVEL 3 // warn
#endif
+#endif
#ifndef AFIO_LOG_TO_OSTREAM
#if !defined(NDEBUG) && !defined(AFIO_DISABLE_LOG_TO_OSTREAM)
@@ -300,26 +307,128 @@ AFIO_V2_NAMESPACE_END
// Bring in a result implementation
#include "outcome/include/outcome.hpp"
AFIO_V2_NAMESPACE_BEGIN
-// Specialise error_code into this namespace so we can hook result creation via ADL
-/*! \struct error_code
-\brief Trampoline to `std::error_code`, used to ADL hook `result<T, E>` creation in Outcome.
+/*! \struct error_info
+\brief The cause of the failure of an operation in AFIO.
+*/
+struct error_info
+{
+ //! The error code for the failure
+ std::error_code ec;
+
+#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
+private:
+ // The id of the thread where this failure occurred
+ uint32_t _thread_id{0};
+ // The TLS path store entry
+ uint16_t _tls_path_id1{(uint16_t) -1}, _tls_path_id2{(uint16_t) -1};
+ // The id of the relevant log entry in the AFIO log (if logging enabled)
+ size_t _log_id{(size_t) -1};
+
+public:
+#endif
+
+ //! Default constructor
+ error_info() = default;
+ //! Construct from a code and error category
+ error_info(int code, const std::error_category &cat)
+ : error_info(std::error_code(code, cat))
+ {
+ }
+ // Construct from an error code
+ inline error_info(std::error_code ec);
+ /* NOTE TO SELF: The error_info constructor implementation is in handle.hpp as we need that
+ defined before we can do useful logging.
+ */
+ //! Construct from an error condition enum
+ OUTCOME_TEMPLATE(class ErrorCondEnum)
+ OUTCOME_TREQUIRES(OUTCOME_TPRED(std::is_error_condition_enum<ErrorCondEnum>::value))
+ error_info(ErrorCondEnum &&v)
+ : error_info(make_error_code(std::forward<ErrorCondEnum>(v)))
+ {
+ }
+
+ //! Retrieve any first path associated with this failure. Note this only works if called from the same thread as where the failure occurred.
+ inline filesystem::path path1() const;
+ //! Retrieve any second path associated with this failure. Note this only works if called from the same thread as where the failure occurred.
+ inline filesystem::path path2() const;
+ //! Retrieve a descriptive message for this failure, possibly with paths and stack backtraces. Extra detail only appears if called from the same thread as where the failure occurred.
+ inline std::string message() const;
+ /*! Throw this failure as a C++ exception. Firstly if the error code matches any of the standard
+ C++ exception types e.g. `bad_alloc`, we throw those types using the string from `message()`
+ where possible. We then will throw an `error` exception type.
+ */
+ inline void throw_as_exception() const;
+};
+inline bool operator==(const error_info &a, const error_info &b)
+{
+ return a.ec == b.ec;
+}
+inline bool operator!=(const error_info &a, const error_info &b)
+{
+ return a.ec != b.ec;
+}
+#ifndef NDEBUG
+// Is trivial in all ways, except default constructibility
+static_assert(std::is_trivially_copyable<error_info>::value, "error_info is not a trivially copyable!");
+#endif
+inline std::ostream &operator<<(std::ostream &s, const error_info &v)
+{
+ if(v.ec)
+ {
+ return s << "afio::error_info(" << v.message() << ")";
+ }
+ return s << "afio::error_info(null)";
+}
+// Tell Outcome that error_info is to be treated as an error_code
+inline std::error_code make_error_code(error_info ei)
+{
+ return ei.ec;
+}
+// Tell Outcome to call error_info::throw_as_exception() on no-value observation
+inline void throw_as_system_error_with_payload(const error_info &ei)
+{
+ ei.throw_as_exception();
+}
+
+/*! \class error
+\brief The exception type synthesised and thrown when an `afio::result` or `afio::outcome` is no-value observed.
*/
-struct error_code : public std::error_code
+class error : public filesystem::filesystem_error
{
- // literally passthrough
- using std::error_code::error_code;
- error_code() = default;
- error_code(std::error_code ec) // NOLINT
- : std::error_code(ec)
+public:
+ error_info ei;
+
+ //! Constructs from an error_info
+ explicit error(error_info _ei)
+ : filesystem::filesystem_error(_ei.message(), _ei.path1(), _ei.path2(), _ei.ec)
+ , ei(_ei)
{
}
};
-template <class T> using result = OUTCOME_V2_NAMESPACE::result<T, error_code>;
-template <class T> using outcome = OUTCOME_V2_NAMESPACE::outcome<T, error_code>;
+
+inline void error_info::throw_as_exception() const
+{
+ std::string msg;
+ try
+ {
+ msg = message();
+ }
+ catch(...)
+ {
+ }
+ OUTCOME_V2_NAMESPACE::try_throw_std_exception_from_error(ec, msg);
+ throw error(*this);
+}
+
+template <class T> using result = OUTCOME_V2_NAMESPACE::result<T, error_info>;
+template <class T> using outcome = OUTCOME_V2_NAMESPACE::outcome<T, error_info>;
using OUTCOME_V2_NAMESPACE::success;
using OUTCOME_V2_NAMESPACE::failure;
using OUTCOME_V2_NAMESPACE::error_from_exception;
using OUTCOME_V2_NAMESPACE::in_place_type;
+
+static_assert(OUTCOME_V2_NAMESPACE::trait::has_error_code_v<error_info>, "error_info is not detected to be an error code");
+
AFIO_V2_NAMESPACE_END
@@ -356,30 +465,18 @@ public:
~log_level_guard() { log().log_level(_v); }
};
-/* Some notes on how error logging works:
-
-Throughout AFIO in almost all of its functions, we call `AFIO_LOG_FUNCTION_CALL(inst)` where `inst` is
-usually `this`. We test if inst points to a `handle`, and if so we replace the "current handle" in
-TLS storage with the new one, restoring it on stack unwind.
-
-When an errored result is created, Outcome provides ADL based hooks which let us intercept an errored
-result creation. We look up TLS storage for the current handle, and if one is set then we fetch its
-current path and store it into a round robin store in TLS, storing the index into the result. Later
-on, when we are reporting or otherwise dealing with the error, the path the error refers to can be
-printed.
-
-All this gets compiled out if AFIO_LOGGING_LEVEL < 2 (error) and is skipped if log().log_level() < 2 (error).
-In this situation, no paths are captured on error.
-*/
-#if AFIO_LOGGING_LEVEL >= 2
+// Infrastructure for recording the current path for when failure occurs
+#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
namespace detail
{
// Our thread local store
struct tls_errored_results_t
{
- handle *current_handle{nullptr}; // The current handle for this thread
- bool reentered{false}; // Whether hook_result_construction is reentering itself
- char paths[190][16]; // The log can only store 190 chars of message anyway
+ uint32_t this_thread_id{QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id()};
+ handle *current_handle{nullptr}; // The current handle for this thread. Changed via RAII via AFIO_LOG_FUNCTION_CALL, see below.
+ bool reentering_self{false}; // Prevents any failed call to current_path() by us reentering ourselves
+
+ char paths[190][16]; // Last 190 chars of path
uint16_t pathidx{0};
char *next(uint16_t &idx)
{
@@ -442,6 +539,66 @@ namespace detail
#else
#define AFIO_LOG_INST_TO_TLS(inst)
#endif
+
+inline filesystem::path error_info::path1() const
+{
+ if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == _thread_id)
+ {
+ auto &tls = detail::tls_errored_results();
+ const char *path1 = tls.get(_tls_path_id1);
+ if(path1 != nullptr)
+ {
+ return filesystem::path(path1);
+ }
+ }
+ return {};
+}
+inline filesystem::path error_info::path2() const
+{
+ if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == _thread_id)
+ {
+ auto &tls = detail::tls_errored_results();
+ const char *path2 = tls.get(_tls_path_id2);
+ if(path2 != nullptr)
+ {
+ return filesystem::path(path2);
+ }
+ }
+ return {};
+}
+inline std::string error_info::message() const
+{
+ std::string ret(ec.message());
+ if(QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id() == _thread_id)
+ {
+ auto &tls = detail::tls_errored_results();
+ const char *path1 = tls.get(_tls_path_id1), *path2 = tls.get(_tls_path_id2);
+ if(path1 != nullptr)
+ {
+ ret.append(" [path1 = ");
+ ret.append(path1);
+ if(path2 != nullptr)
+ {
+ ret.append(", path2 = ");
+ ret.append(path2);
+ }
+ ret.append("]");
+ }
+ }
+#if AFIO_LOGGING_LEVEL >= 2
+ if(_log_id != (uint32_t) -1)
+ {
+ if(log().valid(_log_id))
+ {
+ ret.append(" [location = ");
+ ret.append(location(log()[_log_id]));
+ ret.append("]");
+ }
+ }
+#endif
+ return ret;
+}
+
AFIO_V2_NAMESPACE_END
#ifndef AFIO_LOG_FATAL_TO_CERR
diff --git a/include/afio/v2.0/detail/impl/posix/async_file_handle.ipp b/include/afio/v2.0/detail/impl/posix/async_file_handle.ipp
index cf8e92b5..b6cd0ca2 100644
--- a/include/afio/v2.0/detail/impl/posix/async_file_handle.ipp
+++ b/include/afio/v2.0/detail/impl/posix/async_file_handle.ipp
@@ -88,7 +88,7 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
if(result)
{
if(errcode)
- result = error_code((int) errcode, std::system_category());
+ result = error_info((int) errcode, std::system_category());
else
{
// Figure out which i/o I am and update the buffer in question
diff --git a/include/afio/v2.0/detail/impl/posix/io_handle.ipp b/include/afio/v2.0/detail/impl/posix/io_handle.ipp
index 07db3578..d38d7b51 100644
--- a/include/afio/v2.0/detail/impl/posix/io_handle.ipp
+++ b/include/afio/v2.0/detail/impl/posix/io_handle.ipp
@@ -247,7 +247,7 @@ void io_handle::unlock(io_handle::extent_type offset, io_handle::extent_type byt
}
if(failed)
{
- error_code ret{errno, std::system_category()};
+ error_info ret{errno, std::system_category()};
(void) ret;
AFIO_LOG_FATAL(_v.fd, "io_handle::unlock() failed");
std::terminate();
diff --git a/include/afio/v2.0/detail/impl/windows/async_file_handle.ipp b/include/afio/v2.0/detail/impl/windows/async_file_handle.ipp
index b99ca114..3cb20f2d 100644
--- a/include/afio/v2.0/detail/impl/windows/async_file_handle.ipp
+++ b/include/afio/v2.0/detail/impl/windows/async_file_handle.ipp
@@ -54,7 +54,7 @@ template <class BuffersType, class IORoutine> result<async_file_handle::io_state
if(result)
{
if(errcode)
- result = error_code{errcode, std::system_category()};
+ result = error_info{errcode, std::system_category()};
else
{
// Figure out which i/o I am and update the buffer in question
diff --git a/include/afio/v2.0/detail/impl/windows/fs_handle.ipp b/include/afio/v2.0/detail/impl/windows/fs_handle.ipp
index 64d7870d..0341bfd5 100644
--- a/include/afio/v2.0/detail/impl/windows/fs_handle.ipp
+++ b/include/afio/v2.0/detail/impl/windows/fs_handle.ipp
@@ -182,7 +182,7 @@ result<void> fs_handle::unlink(deadline d) noexcept
{
// If something else is using it, we may not be able to rename
// This error also annoyingly appears if the file has delete on close set on it already
- if(out.error().value() == (int) 0xC0000043 /*STATUS_SHARING_VIOLATION*/)
+ if(out.error().ec.value() == (int) 0xC0000043 /*STATUS_SHARING_VIOLATION*/)
{
AFIO_LOG_WARN(this, "Failed to rename entry to random name to simulate immediate unlinking due to STATUS_SHARING_VIOLATION, skipping");
}
diff --git a/include/afio/v2.0/handle.hpp b/include/afio/v2.0/handle.hpp
index 611008e0..7ccc9216 100644
--- a/include/afio/v2.0/handle.hpp
+++ b/include/afio/v2.0/handle.hpp
@@ -393,49 +393,54 @@ template <class T> struct construct
result<T> operator()() const noexcept { static_assert(!std::is_same<T, T>::value, "construct<T>() was not specialised for the type T supplied"); }
};
-// Intercept when Outcome creates an errored result and log it to our log
-template <class T, class R> inline void hook_result_construction(OUTCOME_V2_NAMESPACE::in_place_type_t<T>, result<R> *res) noexcept
+// failure_info is defined in config.hpp, this is its constructor which needs
+// to be defined here so that we have handle's definition available
+inline error_info::error_info(std::error_code _ec)
+ : ec(_ec)
{
- // Sanity check that we never construct a null error code
- assert(!res->has_error() || res->error().value() != 0);
- if(res->has_error() && log().log_level() >= log_level::error)
+ // Here is a VERY useful place to breakpoint!
+ if(ec)
{
- // Here is a VERY useful place to breakpoint!
+#ifndef AFIO_DISABLE_PATHS_IN_FAILURE_INFO
auto &tls = detail::tls_errored_results();
- handle *currenth = tls.current_handle;
- native_handle_type nativeh;
- if(currenth != nullptr)
+ if(!tls.reentering_self)
{
- if(tls.reentered)
+ handle *currenth = tls.current_handle;
+ native_handle_type nativeh;
+ if(currenth != nullptr)
{
- return;
- }
- tls.reentered = true;
- nativeh = currenth->native_handle();
- auto currentpath_ = currenth->current_path();
- if(currentpath_)
- {
- auto currentpath = currentpath_.value().u8string();
- uint16_t tlsidx = 0;
+ nativeh = currenth->native_handle();
+ // This may fail, if it does it will construct an error_info thus reentering ourselves. Prevent that.
+ tls.reentering_self = true;
+ auto currentpath_ = currenth->current_path();
+ tls.reentering_self = false;
+ if(currentpath_)
+ {
+ auto currentpath = currentpath_.value().u8string();
+ _thread_id = tls.this_thread_id;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996) // the function may be unsafe
#endif
- strncpy(tls.next(tlsidx), QUICKCPPLIB_NAMESPACE::ringbuffer_log::last190(currentpath), 190);
+ strncpy(tls.next(_tls_path_id1), QUICKCPPLIB_NAMESPACE::ringbuffer_log::last190(currentpath), 190);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
- OUTCOME_V2_NAMESPACE::hooks::set_spare_storage(res, tlsidx);
+ _tls_path_id2 = _tls_path_id1 - 17; // guaranteed invalid
+ }
+ }
+#endif
+#if AFIO_LOGGING_LEVEL >= 2
+ if(log().log_level() >= log_level::error)
+ {
+ _log_id = log().emplace_back(log_level::error, ec.message().c_str(), (uint32_t) nativeh._init, tls.this_thread_id);
}
- tls.reentered = false;
+#endif
}
- log().emplace_back(log_level::error, res->assume_error().message().c_str(), (uint32_t) nativeh._init, QUICKCPPLIB_NAMESPACE::utils::thread::this_thread_id());
}
}
-template <class T, class R> inline void hook_result_in_place_construction(OUTCOME_V2_NAMESPACE::in_place_type_t<T> _, result<R> *res) noexcept
-{
- hook_result_construction(_, res);
-}
+
+// Define how we log handles and subclasses thereof
namespace detail
{
template <class T> void log_inst_to_info(const handle *inst, const char *buffer)
diff --git a/include/afio/v2.0/io_handle.hpp b/include/afio/v2.0/io_handle.hpp
index bd012204..49facea7 100644
--- a/include/afio/v2.0/io_handle.hpp
+++ b/include/afio/v2.0/io_handle.hpp
@@ -79,12 +79,12 @@ public:
#ifndef NDEBUG
// Is trivial in all ways, except default constructibility
static_assert(std::is_trivially_copyable<buffers_type>::value, "buffers_type is not trivially copyable!");
- static_assert(std::is_trivially_assignable<buffers_type, buffers_type>::value, "buffers_type is not trivially assignable!");
- static_assert(std::is_trivially_destructible<buffers_type>::value, "buffers_type is not trivially destructible!");
- static_assert(std::is_trivially_copy_constructible<buffers_type>::value, "buffers_type is not trivially copy constructible!");
- static_assert(std::is_trivially_move_constructible<buffers_type>::value, "buffers_type is not trivially move constructible!");
- static_assert(std::is_trivially_copy_assignable<buffers_type>::value, "buffers_type is not trivially copy assignable!");
- static_assert(std::is_trivially_move_assignable<buffers_type>::value, "buffers_type is not trivially move assignable!");
+ // static_assert(std::is_trivially_assignable<buffers_type, buffers_type>::value, "buffers_type is not trivially assignable!");
+ // static_assert(std::is_trivially_destructible<buffers_type>::value, "buffers_type is not trivially destructible!");
+ // static_assert(std::is_trivially_copy_constructible<buffers_type>::value, "buffers_type is not trivially copy constructible!");
+ // static_assert(std::is_trivially_move_constructible<buffers_type>::value, "buffers_type is not trivially move constructible!");
+ // static_assert(std::is_trivially_copy_assignable<buffers_type>::value, "buffers_type is not trivially copy assignable!");
+ // static_assert(std::is_trivially_move_assignable<buffers_type>::value, "buffers_type is not trivially move assignable!");
static_assert(std::is_standard_layout<buffers_type>::value, "buffers_type is not a standard layout type!");
#endif
//! The i/o request type used by this handle. Guaranteed to be `TrivialType` apart from construction, and `StandardLayoutType`.
@@ -106,12 +106,12 @@ public:
#ifndef NDEBUG
// Is trivial in all ways, except default constructibility
static_assert(std::is_trivially_copyable<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially copyable!");
- static_assert(std::is_trivially_assignable<io_request<buffers_type>, io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially assignable!");
- static_assert(std::is_trivially_destructible<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially destructible!");
- static_assert(std::is_trivially_copy_constructible<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially copy constructible!");
- static_assert(std::is_trivially_move_constructible<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially move constructible!");
- static_assert(std::is_trivially_copy_assignable<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially copy assignable!");
- static_assert(std::is_trivially_move_assignable<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially move assignable!");
+ // static_assert(std::is_trivially_assignable<io_request<buffers_type>, io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially assignable!");
+ // static_assert(std::is_trivially_destructible<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially destructible!");
+ // static_assert(std::is_trivially_copy_constructible<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially copy constructible!");
+ // static_assert(std::is_trivially_move_constructible<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially move constructible!");
+ // static_assert(std::is_trivially_copy_assignable<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially copy assignable!");
+ // static_assert(std::is_trivially_move_assignable<io_request<buffers_type>>::value, "io_request<buffers_type> is not trivially move assignable!");
static_assert(std::is_standard_layout<io_request<buffers_type>>::value, "io_request<buffers_type> is not a standard layout type!");
#endif
//! The i/o result type used by this handle. Guaranteed to be `TrivialType` apart from construction..
@@ -153,12 +153,12 @@ public:
#ifndef NDEBUG
// Is trivial in all ways, except default constructibility
static_assert(std::is_trivially_copyable<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially copyable!");
- static_assert(std::is_trivially_assignable<io_result<buffers_type>, io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially assignable!");
- static_assert(std::is_trivially_destructible<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially destructible!");
- static_assert(std::is_trivially_copy_constructible<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially copy constructible!");
- static_assert(std::is_trivially_move_constructible<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially move constructible!");
- static_assert(std::is_trivially_copy_assignable<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially copy assignable!");
- static_assert(std::is_trivially_move_assignable<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially move assignable!");
+// static_assert(std::is_trivially_assignable<io_result<buffers_type>, io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially assignable!");
+// static_assert(std::is_trivially_destructible<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially destructible!");
+// static_assert(std::is_trivially_copy_constructible<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially copy constructible!");
+// static_assert(std::is_trivially_move_constructible<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially move constructible!");
+// static_assert(std::is_trivially_copy_assignable<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially copy assignable!");
+// static_assert(std::is_trivially_move_assignable<io_result<buffers_type>>::value, "io_result<buffers_type> is not trivially move assignable!");
//! \todo Why is io_result<buffers_type> not a standard layout type?
// static_assert(std::is_standard_layout<result<buffers_type>>::value, "result<buffers_type> is not a standard layout type!");
// static_assert(std::is_standard_layout<io_result<buffers_type>>::value, "io_result<buffers_type> is not a standard layout type!");
diff --git a/include/afio/v2.0/map_handle.hpp b/include/afio/v2.0/map_handle.hpp
index d0e15c82..59fcef86 100644
--- a/include/afio/v2.0/map_handle.hpp
+++ b/include/afio/v2.0/map_handle.hpp
@@ -236,17 +236,14 @@ public:
template <class T> using io_result = io_handle::io_result<T>;
protected:
- section_handle *_section;
- char *_addr;
- extent_type _offset;
- size_type _length;
- section_handle::flag _flag;
+ section_handle *_section{nullptr};
+ char *_addr{nullptr};
+ extent_type _offset{0};
+ size_type _length{0};
+ section_handle::flag _flag{section_handle::flag::none};
explicit map_handle(section_handle *section)
: _section(section)
- , _addr(nullptr)
- , _offset(0)
- , _length(0)
, _flag(section ? section->section_flags() : section_handle::flag::none)
{
}
@@ -255,11 +252,6 @@ public:
//! Default constructor
constexpr map_handle()
: io_handle()
- , _section(nullptr)
- , _addr(nullptr)
- , _offset(0)
- , _length(0)
- , _flag(section_handle::flag::none)
{
}
AFIO_HEADERS_ONLY_VIRTUAL_SPEC ~map_handle();
diff --git a/include/afio/v2.0/stat.hpp b/include/afio/v2.0/stat.hpp
index f1c45668..c82f89d3 100644
--- a/include/afio/v2.0/stat.hpp
+++ b/include/afio/v2.0/stat.hpp
@@ -135,7 +135,7 @@ struct stat_t
{
auto v(fill(h, wanted));
if(v.has_error())
- throw std::system_error(v.error());
+ v.error().throw_as_exception();
}
#endif
//! Fills in the structure with metadata, returning number of items filled in
diff --git a/include/afio/v2.0/statfs.hpp b/include/afio/v2.0/statfs.hpp
index 16c2f312..0027ea7a 100644
--- a/include/afio/v2.0/statfs.hpp
+++ b/include/afio/v2.0/statfs.hpp
@@ -90,7 +90,7 @@ struct AFIO_DECL statfs_t
{
auto v(fill(h, wanted));
if(v.has_error())
- throw std::system_error(v.error());
+ v.error().throw_as_exception();
}
#endif
//! Fills in the structure with metadata, returning number of items filled in
diff --git a/test/test_kernel_decl.hpp b/test/test_kernel_decl.hpp
index fcbb4905..58999aaa 100644
--- a/test/test_kernel_decl.hpp
+++ b/test/test_kernel_decl.hpp
@@ -34,4 +34,55 @@ Distributed under the Boost Software License, Version 1.0.
#define AFIO_TEST_KERNEL_DECL extern QUICKCPPLIB_SYMBOL_EXPORT
#endif
+#include "kerneltest/include/kerneltest.hpp"
+
+#if 0
+// Tell KernelTest's outcome how to grok AFIO's result
+OUTCOME_V2_NAMESPACE_BEGIN
+namespace convert
+{
+ // Provide custom ValueOrError conversion from afio::result<U> into kerneltest::result<T>
+ template <class T, class U> struct value_or_error<KERNELTEST_V1_NAMESPACE::result<T>, AFIO_V2_NAMESPACE::result<U>>
+ {
+ static constexpr bool enable_result_inputs = true;
+ static constexpr bool enable_outcome_inputs = true;
+
+ template <class X, //
+ typename = std::enable_if_t<std::is_same<AFIO_V2_NAMESPACE::result<U>, std::decay_t<X>>::value //
+ && std::is_constructible<T, U>::value>> //
+ constexpr KERNELTEST_V1_NAMESPACE::result<T>
+ operator()(X &&src)
+ {
+ // Forward exactly
+ return src.has_value() ? //
+ KERNELTEST_V1_NAMESPACE::result<T>{std::forward<X>(src).value()} //
+ :
+ KERNELTEST_V1_NAMESPACE::result<T>{make_error_code(std::forward<X>(src).error())};
+ }
+ };
+ // Provide custom ValueOrError conversion from afio::result<U> into kerneltest::outcome<T>
+ template <class T, class U> struct value_or_error<KERNELTEST_V1_NAMESPACE::outcome<T>, AFIO_V2_NAMESPACE::result<U>>
+ {
+ static constexpr bool enable_result_inputs = true;
+ static constexpr bool enable_outcome_inputs = true;
+
+ template <class X, //
+ typename = std::enable_if_t<std::is_same<AFIO_V2_NAMESPACE::result<U>, std::decay_t<X>>::value //
+ && std::is_constructible<T, U>::value>> //
+ constexpr KERNELTEST_V1_NAMESPACE::outcome<T>
+ operator()(X &&src)
+ {
+ // Forward exactly
+ return src.has_value() ? //
+ KERNELTEST_V1_NAMESPACE::outcome<T>{std::forward<X>(src).value()} //
+ :
+ KERNELTEST_V1_NAMESPACE::outcome<T>{make_error_code(std::forward<X>(src).error())};
+ }
+ };
+}
+OUTCOME_V2_NAMESPACE_END
+static_assert(std::is_constructible<KERNELTEST_V1_NAMESPACE::result<int>, AFIO_V2_NAMESPACE::result<int>>::value, "kerneltest::result<int> is not constructible from afio::result<int>!");
+static_assert(std::is_constructible<KERNELTEST_V1_NAMESPACE::outcome<int>, AFIO_V2_NAMESPACE::result<int>>::value, "kerneltest::outcome<int> is not constructible from afio::result<int>!");
+#endif
+
#endif // namespace
diff --git a/test/tests/async_io.cpp b/test/tests/async_io.cpp
index acf3dc07..1a0609fb 100644
--- a/test/tests/async_io.cpp
+++ b/test/tests/async_io.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
#include <future>
@@ -67,7 +66,7 @@ static inline void TestAsyncFileHandle()
for(auto &i : futures)
{
afio::async_file_handle::const_buffers_type out = i.first.get();
- //std::cout << out.data()->len << std::endl;
+ // std::cout << out.data()->len << std::endl;
BOOST_CHECK(out.data()->len == 4096);
}
}
diff --git a/test/tests/coroutines.cpp b/test/tests/coroutines.cpp
index c5fa3065..b39fc24f 100644
--- a/test/tests/coroutines.cpp
+++ b/test/tests/coroutines.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
#include <future>
diff --git a/test/tests/current_path.cpp b/test/tests/current_path.cpp
index 64d0f3f8..3f2ae559 100644
--- a/test/tests/current_path.cpp
+++ b/test/tests/current_path.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
template <class FileHandleType, class DirectoryHandleType> static inline void TestHandleCurrentPath()
{
diff --git a/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp b/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp
index 87d1d5c9..4d064069 100644
--- a/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp
+++ b/test/tests/directory_handle_create_close/kernel_directory_handle.cpp.hpp
@@ -23,25 +23,24 @@ Distributed under the Boost Software License, Version 1.0.
*/
#include "../../test_kernel_decl.hpp"
-#include "kerneltest/include/kerneltest.hpp"
namespace directory_handle_create_close
{
AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle> test_kernel_directory_handle_absolute(AFIO_V2_NAMESPACE::directory_handle::mode m, AFIO_V2_NAMESPACE::directory_handle::creation c, AFIO_V2_NAMESPACE::directory_handle::flag f,
- AFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, KERNELTEST_V1_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
+ AFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
{
auto h = AFIO_V2_NAMESPACE::directory_handle::directory({}, "testdir", m, c, AFIO_V2_NAMESPACE::directory_handle::caching::all, f);
if(h)
{
// git needs a file in a directory to create it, so any directory created needs an empty file called pin.txt
(void) AFIO_V2_NAMESPACE::file_handle::file(h.value(), "pin.txt", AFIO_V2_NAMESPACE::file_handle::mode::write, AFIO_V2_NAMESPACE::file_handle::creation::if_needed);
- *info = KERNELTEST_V1_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
+ *info = AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
h.value().close().value();
}
return h;
}
AFIO_TEST_KERNEL_DECL AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle> test_kernel_directory_handle_relative(AFIO_V2_NAMESPACE::directory_handle::mode m, AFIO_V2_NAMESPACE::directory_handle::creation c, AFIO_V2_NAMESPACE::directory_handle::flag f,
- AFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, KERNELTEST_V1_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
+ AFIO_V2_NAMESPACE::directory_handle::buffers_type *entries, AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info> *info)
{
OUTCOME_TRY(b, AFIO_V2_NAMESPACE::path_handle::path("."));
auto h = AFIO_V2_NAMESPACE::directory_handle::directory(b, "testdir", m, c, AFIO_V2_NAMESPACE::directory_handle::caching::all, f);
@@ -49,7 +48,7 @@ namespace directory_handle_create_close
{
// git needs a file in a directory to create it, so any directory created needs an empty file called pin.txt
(void) AFIO_V2_NAMESPACE::file_handle::file(h.value(), "pin.txt", AFIO_V2_NAMESPACE::file_handle::mode::write, AFIO_V2_NAMESPACE::file_handle::creation::if_needed);
- *info = KERNELTEST_V1_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
+ *info = AFIO_V2_NAMESPACE::result<AFIO_V2_NAMESPACE::directory_handle::enumerate_info>(h.value().enumerate(std::move(*entries)));
h.value().close().value();
}
b.close().value();
diff --git a/test/tests/directory_handle_create_close/runner.cpp b/test/tests/directory_handle_create_close/runner.cpp
index 6b1aa2f4..d3e499c0 100644
--- a/test/tests/directory_handle_create_close/runner.cpp
+++ b/test/tests/directory_handle_create_close/runner.cpp
@@ -23,11 +23,11 @@ Distributed under the Boost Software License, Version 1.0.
*/
#include "kernel_directory_handle.cpp.hpp"
-#include "kerneltest/include/kerneltest.hpp"
template <class U> inline void directory_handle_create_close_creation(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
+ using AFIO_V2_NAMESPACE::result;
using directory_handle = AFIO_V2_NAMESPACE::directory_handle;
static const result<void> no_such_file_or_directory = std::errc::no_such_file_or_directory;
static const result<void> file_exists = std::errc::file_exists;
diff --git a/test/tests/directory_handle_enumerate/runner.cpp b/test/tests/directory_handle_enumerate/runner.cpp
index da99714b..4e28c444 100644
--- a/test/tests/directory_handle_enumerate/runner.cpp
+++ b/test/tests/directory_handle_enumerate/runner.cpp
@@ -23,11 +23,11 @@ Distributed under the Boost Software License, Version 1.0.
*/
#include "kernel_directory_handle_enumerate.cpp.hpp"
-#include "kerneltest/include/kerneltest.hpp"
template <class U> inline void directory_handle_enumerate_(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
+ using AFIO_V2_NAMESPACE::result;
using AFIO_V2_NAMESPACE::path_view;
using AFIO_V2_NAMESPACE::directory_entry;
using AFIO_V2_NAMESPACE::directory_handle;
diff --git a/test/tests/file_handle_create_close/runner.cpp b/test/tests/file_handle_create_close/runner.cpp
index 06360a74..75e4088e 100644
--- a/test/tests/file_handle_create_close/runner.cpp
+++ b/test/tests/file_handle_create_close/runner.cpp
@@ -22,13 +22,13 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "kerneltest/include/kerneltest.hpp"
#include "kernel_async_file_handle.cpp.hpp"
#include "kernel_file_handle.cpp.hpp"
template <class U> inline void file_handle_create_close_creation(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
+ using AFIO_V2_NAMESPACE::result;
using file_handle = AFIO_V2_NAMESPACE::file_handle;
static const result<void> no_such_file_or_directory = std::errc::no_such_file_or_directory;
static const result<void> file_exists = std::errc::file_exists;
diff --git a/test/tests/file_handle_lock_unlock.cpp b/test/tests/file_handle_lock_unlock.cpp
index 8a1218de..db4d266d 100644
--- a/test/tests/file_handle_lock_unlock.cpp
+++ b/test/tests/file_handle_lock_unlock.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
static inline void TestFileHandleLockUnlock()
{
diff --git a/test/tests/map_handle_create_close/runner.cpp b/test/tests/map_handle_create_close/runner.cpp
index fb4c605d..0baedef5 100644
--- a/test/tests/map_handle_create_close/runner.cpp
+++ b/test/tests/map_handle_create_close/runner.cpp
@@ -23,11 +23,11 @@ Distributed under the Boost Software License, Version 1.0.
*/
#include "kernel_map_handle.cpp.hpp"
-#include "kerneltest/include/kerneltest.hpp"
template <class U> inline void map_handle_create_close_(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
+ using AFIO_V2_NAMESPACE::result;
using AFIO_V2_NAMESPACE::file_handle;
using AFIO_V2_NAMESPACE::section_handle;
using AFIO_V2_NAMESPACE::map_handle;
diff --git a/test/tests/mapped_view.cpp b/test/tests/mapped_view.cpp
index 124a5865..3303bb0d 100644
--- a/test/tests/mapped_view.cpp
+++ b/test/tests/mapped_view.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
static inline void TestMappedView1()
{
diff --git a/test/tests/path_discovery.cpp b/test/tests/path_discovery.cpp
index bbd76f08..d9f1a150 100644
--- a/test/tests/path_discovery.cpp
+++ b/test/tests/path_discovery.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
static inline void TestPathDiscovery()
{
diff --git a/test/tests/path_view.cpp b/test/tests/path_view.cpp
index b860cf33..ccdcba11 100644
--- a/test/tests/path_view.cpp
+++ b/test/tests/path_view.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
static inline void TestPathView()
{
diff --git a/test/tests/section_handle_create_close/runner.cpp b/test/tests/section_handle_create_close/runner.cpp
index 4b8ba2ae..507886bb 100644
--- a/test/tests/section_handle_create_close/runner.cpp
+++ b/test/tests/section_handle_create_close/runner.cpp
@@ -23,11 +23,11 @@ Distributed under the Boost Software License, Version 1.0.
*/
#include "kernel_section_handle.cpp.hpp"
-#include "kerneltest/include/kerneltest.hpp"
template <class U> inline void section_handle_create_close_(U &&f)
{
using namespace KERNELTEST_V1_NAMESPACE;
+ using AFIO_V2_NAMESPACE::result;
using AFIO_V2_NAMESPACE::file_handle;
using AFIO_V2_NAMESPACE::section_handle;
namespace path_discovery = AFIO_V2_NAMESPACE::path_discovery;
diff --git a/test/tests/shared_fs_mutex.cpp b/test/tests/shared_fs_mutex.cpp
index 06e029d1..a5cf8cdf 100644
--- a/test/tests/shared_fs_mutex.cpp
+++ b/test/tests/shared_fs_mutex.cpp
@@ -24,8 +24,7 @@ Distributed under the Boost Software License, Version 1.0.
#define QUICKCPPLIB_BOOST_UNIT_TEST_CUSTOM_MAIN_DEFINED
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
KERNELTEST_TEST_KERNEL(unit, afio, shared_fs_mutex, entity_endian, "Tests that afio::algorithm::shared_fs_mutex::entity_type has the right endian", [] {
AFIO_V2_NAMESPACE::algorithm::shared_fs_mutex::shared_fs_mutex::entity_type v(0, true);
diff --git a/test/tests/trivial_vector.cpp b/test/tests/trivial_vector.cpp
index ac263ac3..6c8b542f 100644
--- a/test/tests/trivial_vector.cpp
+++ b/test/tests/trivial_vector.cpp
@@ -22,8 +22,7 @@ Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "../../include/afio/afio.hpp"
-#include "kerneltest/include/kerneltest.hpp"
+#include "../test_kernel_decl.hpp"
static size_t trivial_vector_udts_constructed;
static inline void TestTrivialVector()