diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/common_funcs.h | 6 | ||||
| -rw-r--r-- | src/common/fiber.cpp | 23 | ||||
| -rw-r--r-- | src/common/fiber.h | 2 | ||||
| -rw-r--r-- | src/common/misc.cpp | 44 |
4 files changed, 48 insertions, 27 deletions
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 71b64e32a..4ace2cd33 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -52,9 +52,13 @@ __declspec(dllimport) void __stdcall DebugBreak(void); | |||
| 52 | // Generic function to get last error message. | 52 | // Generic function to get last error message. |
| 53 | // Call directly after the command or use the error num. | 53 | // Call directly after the command or use the error num. |
| 54 | // This function might change the error code. | 54 | // This function might change the error code. |
| 55 | // Defined in Misc.cpp. | 55 | // Defined in misc.cpp. |
| 56 | [[nodiscard]] std::string GetLastErrorMsg(); | 56 | [[nodiscard]] std::string GetLastErrorMsg(); |
| 57 | 57 | ||
| 58 | // Like GetLastErrorMsg(), but passing an explicit error code. | ||
| 59 | // Defined in misc.cpp. | ||
| 60 | [[nodiscard]] std::string NativeErrorToString(int e); | ||
| 61 | |||
| 58 | #define DECLARE_ENUM_FLAG_OPERATORS(type) \ | 62 | #define DECLARE_ENUM_FLAG_OPERATORS(type) \ |
| 59 | [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ | 63 | [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ |
| 60 | using T = std::underlying_type_t<type>; \ | 64 | using T = std::underlying_type_t<type>; \ |
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index 3c1eefcb7..39532ff58 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp | |||
| @@ -116,16 +116,19 @@ void Fiber::Rewind() { | |||
| 116 | boost::context::detail::jump_fcontext(impl->rewind_context, this); | 116 | boost::context::detail::jump_fcontext(impl->rewind_context, this); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { | 119 | void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) { |
| 120 | ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); | 120 | to.impl->guard.lock(); |
| 121 | ASSERT_MSG(to != nullptr, "Next fiber is null!"); | 121 | to.impl->previous_fiber = weak_from.lock(); |
| 122 | to->impl->guard.lock(); | 122 | |
| 123 | to->impl->previous_fiber = from; | 123 | auto transfer = boost::context::detail::jump_fcontext(to.impl->context, &to); |
| 124 | auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get()); | 124 | |
| 125 | ASSERT(from->impl->previous_fiber != nullptr); | 125 | // "from" might no longer be valid if the thread was killed |
| 126 | from->impl->previous_fiber->impl->context = transfer.fctx; | 126 | if (auto from = weak_from.lock()) { |
| 127 | from->impl->previous_fiber->impl->guard.unlock(); | 127 | ASSERT(from->impl->previous_fiber != nullptr); |
| 128 | from->impl->previous_fiber.reset(); | 128 | from->impl->previous_fiber->impl->context = transfer.fctx; |
| 129 | from->impl->previous_fiber->impl->guard.unlock(); | ||
| 130 | from->impl->previous_fiber.reset(); | ||
| 131 | } | ||
| 129 | } | 132 | } |
| 130 | 133 | ||
| 131 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { | 134 | std::shared_ptr<Fiber> Fiber::ThreadToFiber() { |
diff --git a/src/common/fiber.h b/src/common/fiber.h index f7f587f8c..f2a8ff29a 100644 --- a/src/common/fiber.h +++ b/src/common/fiber.h | |||
| @@ -41,7 +41,7 @@ public: | |||
| 41 | 41 | ||
| 42 | /// Yields control from Fiber 'from' to Fiber 'to' | 42 | /// Yields control from Fiber 'from' to Fiber 'to' |
| 43 | /// Fiber 'from' must be the currently running fiber. | 43 | /// Fiber 'from' must be the currently running fiber. |
| 44 | static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to); | 44 | static void YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to); |
| 45 | [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber(); | 45 | [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber(); |
| 46 | 46 | ||
| 47 | void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param); | 47 | void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param); |
diff --git a/src/common/misc.cpp b/src/common/misc.cpp index 1d5393597..495385b9e 100644 --- a/src/common/misc.cpp +++ b/src/common/misc.cpp | |||
| @@ -12,27 +12,41 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/common_funcs.h" | 13 | #include "common/common_funcs.h" |
| 14 | 14 | ||
| 15 | // Generic function to get last error message. | 15 | std::string NativeErrorToString(int e) { |
| 16 | // Call directly after the command or use the error num. | ||
| 17 | // This function might change the error code. | ||
| 18 | std::string GetLastErrorMsg() { | ||
| 19 | static constexpr std::size_t buff_size = 255; | ||
| 20 | char err_str[buff_size]; | ||
| 21 | |||
| 22 | #ifdef _WIN32 | 16 | #ifdef _WIN32 |
| 23 | FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), | 17 | LPSTR err_str; |
| 24 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, nullptr); | 18 | |
| 25 | return std::string(err_str, buff_size); | 19 | DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 26 | #elif defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) | 20 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 21 | nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||
| 22 | reinterpret_cast<LPSTR>(&err_str), 1, nullptr); | ||
| 23 | if (!res) { | ||
| 24 | return "(FormatMessageA failed to format error)"; | ||
| 25 | } | ||
| 26 | std::string ret(err_str); | ||
| 27 | LocalFree(err_str); | ||
| 28 | return ret; | ||
| 29 | #else | ||
| 30 | char err_str[255]; | ||
| 31 | #if defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) | ||
| 27 | // Thread safe (GNU-specific) | 32 | // Thread safe (GNU-specific) |
| 28 | const char* str = strerror_r(errno, err_str, buff_size); | 33 | const char* str = strerror_r(e, err_str, sizeof(err_str)); |
| 29 | return std::string(str); | 34 | return std::string(str); |
| 30 | #else | 35 | #else |
| 31 | // Thread safe (XSI-compliant) | 36 | // Thread safe (XSI-compliant) |
| 32 | const int success = strerror_r(errno, err_str, buff_size); | 37 | int second_err = strerror_r(e, err_str, sizeof(err_str)); |
| 33 | if (success != 0) { | 38 | if (second_err != 0) { |
| 34 | return {}; | 39 | return "(strerror_r failed to format error)"; |
| 35 | } | 40 | } |
| 36 | return std::string(err_str); | 41 | return std::string(err_str); |
| 42 | #endif // GLIBC etc. | ||
| 43 | #endif // _WIN32 | ||
| 44 | } | ||
| 45 | |||
| 46 | std::string GetLastErrorMsg() { | ||
| 47 | #ifdef _WIN32 | ||
| 48 | return NativeErrorToString(GetLastError()); | ||
| 49 | #else | ||
| 50 | return NativeErrorToString(errno); | ||
| 37 | #endif | 51 | #endif |
| 38 | } | 52 | } |