#include <sys/mman.h> #ifdef __APPLE__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdeprecated-declarations" # include <ucontext.h> #endif template<typename ReturnType> sprawl::threading::CoroutineBase::Holder<ReturnType>::Holder() : m_function(nullptr) , m_stackSize(0) , m_stack(nullptr) , m_stackPointer(nullptr) , m_state(CoroutineState::Created) , m_context() , m_refCount(1) , m_priorCoroutine(nullptr) { m_stackPointer = &m_context; getcontext(&m_context); } template<typename ReturnType> /*virtual*/ sprawl::threading::CoroutineBase::Holder<ReturnType>::~Holder() { if(m_stack) { munmap(m_stack, m_stackSize); } } template<typename ReturnType> sprawl::threading::CoroutineBase::Holder<ReturnType>::Holder(std::function<ReturnType()> function, size_t stackSize) : m_function(function) , m_stackSize(stackSize == 0 ? 1024 * 1024 : stackSize) , m_stack(nullptr) , m_stackPointer(nullptr) , m_state(CoroutineState::Created) , m_context() , m_refCount(1) , m_priorCoroutine(nullptr) { m_stack = mmap(NULL, m_stackSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); m_stackPointer = &m_context; getcontext(&m_context); m_context.uc_link = nullptr; m_context.uc_stack.ss_sp = m_stack; m_context.uc_stack.ss_size = m_stackSize; makecontext(&m_context, &CoroutineBase::entryPoint_, 0); } #ifdef __APPLE__ # pragma GCC diagnostic pop #endif
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 23398 | ququlala | "Forking branch Mainline of shadauxcat-libsprawl to ququlala-libsprawl." | ||
//guest/ShadauxCat/Sprawl/Mainline/threading/coroutine_linux.inl | |||||
#1 | 16179 | ShadauxCat |
- Added SPRAWL_DEBUG macro - Added additional runtime coroutine safety checks against not only wrong type of coroutine, but wrong send/receive type - Added ability to disable these additional runtime checks (and defaulted them to turned off in release builds) as they entail up to three virtual function calls and possibly an exception (when exceptions are enabled) - Added requirement that a coroutine that can yield a value must call a function that returns a value of the same type - this ensures that after the last value from the function has been received, the function doesn't have to be called again (with potentially unpredictable results...) to put it into the "Completed" state. Now the last value must be transmitted with a full return, so the last value and the "Completed" state come around at the same time. (This involves all sorts of ca-razy assumptions and reinterpret_casting... assumptions protected via static_assert) #review-16180 |