#include "thread.hpp" #include "../time/time.hpp" #include <time.h> #ifdef __APPLE__ #include <sched.h> # define pthread_yield sched_yield #endif #include "../common/compat.hpp" namespace ThreadStatic { static void* EntryPoint(void *data) { sprawl::threading::Thread* thread = reinterpret_cast<sprawl::threading::Thread*>(data); sprawl::threading::RunThread(thread); return nullptr; } } /*static*/ sprawl::threading::ThreadDestructionBehavior sprawl::threading::Thread::ms_defaultDestructionBehavior = sprawl::threading::ThreadDestructionBehavior::Abort; int64_t sprawl::threading::Handle::GetUniqueId() const { return int64_t(m_thread); } void sprawl::threading::Thread::Start() { int result = pthread_create(&m_handle.GetNativeHandle(), nullptr, &ThreadStatic::EntryPoint, this); #ifndef __APPLE__ if(result == 0) { if(m_threadName != nullptr) { pthread_setname_np(m_handle.GetNativeHandle(), m_threadName); } } #endif } void sprawl::threading::Thread::PlatformJoin() { void* value; pthread_join(m_handle.GetNativeHandle(), &value); } void sprawl::threading::Thread::PlatformDetach() { pthread_detach(m_handle.GetNativeHandle()); } sprawl::threading::Handle sprawl::this_thread::GetHandle() { return sprawl::threading::Handle(pthread_self()); } sprawl::threading::Thread::~Thread() { if(m_destructionBehavior == ThreadDestructionBehavior::Default) { m_destructionBehavior = ms_defaultDestructionBehavior; } if(Joinable()) { #if SPRAWL_EXCEPTIONS_ENABLED if(m_exception) { try { std::rethrow_exception(m_exception); } catch(std::exception& e) { fprintf(stderr, "Thread %" SPRAWL_I64FMT "d destroyed without being joined after thread was terminated with a std::exception. e.what(): %s\n", GetHandle().GetUniqueId(), e.what()); } catch(...) { fprintf(stderr, "Thread %" SPRAWL_I64FMT "d destroyed without being joined after thread was terminated with an exception of unknown type.\n", GetHandle().GetUniqueId()); } fflush(stderr); std::terminate(); } #endif switch(m_destructionBehavior) { case ThreadDestructionBehavior::Abort: case ThreadDestructionBehavior::Default: default: std::terminate(); break; case ThreadDestructionBehavior::Detach: PlatformDetach(); break; case ThreadDestructionBehavior::Join: PlatformJoin(); break; } } } void sprawl::this_thread::Sleep(uint64_t nanoseconds) { struct timespec ts; ts.tv_sec = time_t(sprawl::time::Convert(nanoseconds, sprawl::time::Resolution::Nanoseconds, sprawl::time::Resolution::Seconds)); int64_t secsAsNanosecs = sprawl::time::Convert(ts.tv_sec, sprawl::time::Resolution::Seconds, sprawl::time::Resolution::Nanoseconds); ts.tv_nsec = long(nanoseconds - secsAsNanosecs); nanosleep(&ts, nullptr); } void sprawl::this_thread::SleepUntil(uint64_t nanosecondTimestamp) { Sleep(nanosecondTimestamp - sprawl::time::Now(sprawl::time::Resolution::Nanoseconds)); } void sprawl::this_thread::Yield() { pthread_yield(); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 23398 | ququlala | "Forking branch Mainline of shadauxcat-libsprawl to ququlala-libsprawl." | ||
//guest/ShadauxCat/Sprawl/Mainline/threading/thread_linux.cpp | |||||
#7 | 16768 | ShadauxCat |
Improvements to error handling in builds with exceptions disabled: - In debug builds or with SPRAWL_ERRORSTATE_STRICT enabled, ErrorState will output a message to stderr and terminate if Get() is called when an error flag is set. (In release buils or with SPRAWL_ERRORSTATE_PERMISSIVE defined, Get() will return junk memory in this case.) - In debug builds or with SPRAWL_ERRORSTATE_STRICT enabled, ErrorState will output a message to stderr and terminate if its destructor is called without checking the errorstate if an error is present (equivalent to an exception terminating the application if no catch() block is present for it). - On linux builds and when running "Analyze" through visual studio, a warning will be issued if any function returning ErrorState has its return value ignored. (This only applies to builds with exceptions not enabled; when exceptions are enabled no warning is issued) - Many functions that could return ErrorState were having their return values silently ignored in internal sprawl code so the user would not find out about errors if exceptions are disabled; now anything in sprawl code that calls a function returning ErrorState will either handle the error, or (in most cases) surface it back up to the user. - As a positive side-effect of the warnings for ignoring ErrorState, several constructors that were capable of throwing exceptions are no longer capable of doing so. #review-16769 |
||
#6 | 16133 | ShadauxCat |
Fixed missing header in thread_linux.hpp #review-16134 |
||
#5 | 16131 | ShadauxCat |
- Exposed FILE* object in sprawl::filesystem::File - Added ability to specify flush behavior for custom handlers via std::function (interesting note - apparently with optimization enabled, calls to std::function can execute faster than virtual function calls) - Threads that destruct with no Join() after exiting with an uncaught exception will terminate with an error message rather than swallowing the exception and letting it disappear #review-16132 |
||
#4 | 16111 | ShadauxCat |
- Threads can now optionally catch exceptions to be rethrown on another thread when it calls Join(). The exception state of a thread can also be queried via HasException() - if this returns true, the thread exited due to an uncaught exception that will be rethrown on Join(). - The behavior of the thread destructor can now be manipulated via SetDestructionBehavior(). By default, a thread whose destructor is called without Join() being called on it will call std::terminate(). But that behavior can be changed such that the destructor can either call Join() automatically, or detach the thread, if it destructs without Join() being called. (If it calls Join() on a thread that caught an exception, the exception will NOT be rethrown, it will be lost to the aether. Throwing exceptions in a destructor is bad, but I'm on the fence whether this should just throw those exceptions away or call std::terminate() in that case. Open for input.) #review-16112 |
||
#3 | 14216 | ShadauxCat |
-Moved some global sprawl::Strings into local scope in json serialization test because of initialization order issues in the memory allocator on mac. This is a temporary fix, and a real fix will come by making the pool allocator work in explicitly-sized pieces and putting all the code for those pieces into a cpp file. -Fixed a large number of warnings on mac/linux that were exposed by fixes to csbuild -Fixed compile errors on mac due to malloc and alloca not being defined, fixed by #include <stdlib.h> in appropriate places -Fixed mac os x trying to link against pthread erroneously -Provided os x implementation of time library -Fixed compile errors on os x due to std::unordered_map whining about the difference between an allocator that allocates std::pair<key, value> and one that allocates std::pair<key const, value>, which, of course, is that the allocator will be no different at all. -Fixed an actual issue where one unordered_map was allocating only key_type instead of std::pair<key_type, value_type> -Fixed a memory leak where coroutine objects would never be cleaned up because either Yield() or reactivate_() will never return (and thus never clean up their stack memory and thus never release any dynamic memory held in stack objects) depending on the situation - if the function runs to completion, reactivate_() never returns after calling swapcontext(); meanwhile, if the function does not run to completion, Yield() never returns after calling Pause(). This behavior will need to be well-documented because it will affect client-side code as well. Stack memory within a coroutine should not rely on RAII behavior. -Fixed compile failure when creating a StlWrapper with a const value_type #review-14217 |
||
#2 | 13650 | ShadauxCat |
- Windows implementations of thread and time libraries - Added coroutines - Added some more unit tests, fixed some unit tests in windows environments - Fixed an issue where multi threading was not properly detected on Linux - Fixed the makefiles to build with threading by default on linux - Changed the pool allocator to use thread-local pools instead of locking mutexes - Fixed output of sprawl::string in the StringBuilder library to take length into account - Added string builder options for StringLiteral - Added thread local implementation #review |
||
#1 | 12508 | ShadauxCat |
-Added threading library. Currently only functional for Linux; Windows will fail to link. (I will fix this soon.) -Fixed missing move and copy constructors in List and ForwardList -Fixed broken move constructor in HashMap -Fixed missing const get() in HashMap -Fixed broken operator-> in ListIterator -Added sprawl::noncopyable -Added sketch headers for filesystem library -Made StringLiteral hashable, added special hashes for pointers and integers in murmur3 -Fixed compiler warning in async_network -Updated memory allocators to use new threading library for mutexes -Added accessibility to sprawl::StringLiteral to be able toa ccess its pointer and length and perform pointer comparisons #review-12504 |