coroutine.cpp #2

  • //
  • guest/
  • brandon_m_bare/
  • Sprawl/
  • brandon_m_bare/
  • threading/
  • coroutine.cpp
  • View
  • Commits
  • Open Download .zip Download (2 KB)
#include "coroutine.hpp"

/*static*/ sprawl::threading::ThreadLocal<sprawl::threading::CoroutineBase*> sprawl::threading::CoroutineBase::ms_coroutineInitHelper;
/*static*/ sprawl::threading::ThreadLocal<sprawl::threading::CoroutineBase> sprawl::threading::CoroutineBase::ms_thisThreadCoroutine;

sprawl::threading::CoroutineBase::CoroutineBase()
	: m_holder(Holder<void>::Create())
	, m_ownsHolder(true)
{
	// NOP
}

sprawl::threading::CoroutineBase::CoroutineBase(sprawl::threading::CoroutineBase::Holder<void>* holder)
	: m_holder(holder)
	, m_ownsHolder(true)
{
	if(m_holder && !ms_thisThreadCoroutine)
	{
		ms_thisThreadCoroutine = CoroutineBase();
	}
}

sprawl::threading::CoroutineBase::CoroutineBase(CoroutineBase const& other)
	: m_holder(other.m_holder)
	, m_ownsHolder(true)
{
	m_holder->IncRef();
}

sprawl::threading::CoroutineBase& sprawl::threading::CoroutineBase::operator =(CoroutineBase const& other)
{
	if(m_ownsHolder && m_holder && m_holder->DecRef())
	{
		m_holder->Release();
	}
	m_holder = other.m_holder;
	if(m_ownsHolder && m_holder)
	{
		m_holder->IncRef();
	}
	return *this;
}

sprawl::threading::CoroutineBase::~CoroutineBase()
{
	if(m_ownsHolder && m_holder && m_holder->DecRef())
	{
		m_holder->Release();
	}
}

sprawl::threading::CoroutineState sprawl::threading::CoroutineBase::State()
{
	return m_holder ? m_holder->m_state : CoroutineState::Invalid;
}

void sprawl::threading::CoroutineBase::run_()
{
#if SPRAWL_EXCEPTIONS_ENABLED
	try
	{
		m_holder->RunFunction();
	}
	catch(...)
	{
		m_holder->m_exception = std::current_exception();
	}
#else
	m_holder->RunFunction();
#endif
	m_holder->m_state = CoroutineState::Completed;
	m_holder->m_priorCoroutine.reactivate_();
}

/*static*/ void sprawl::threading::CoroutineBase::entryPoint_()
{
	ms_coroutineInitHelper->run_();
}

void sprawl::threading::CoroutineBase::releaseRef_()
{
	if(m_holder && m_ownsHolder)
	{
		m_holder->DecRef();
		m_ownsHolder = false;
	}
}

size_t sprawl::threading::CoroutineBase::StackSize()
{
	return m_holder->m_stackSize;
}

/*static*/ sprawl::threading::CoroutineBase sprawl::threading::CoroutineBase::GetCurrentCoroutine()
{
	return *ms_thisThreadCoroutine;
}

sprawl::threading::CoroutineBase sprawl::threading::CoroutineBase::GetCallingCoroutine()
{
	return m_holder->m_priorCoroutine;
}

sprawl::threading::CoroutineType sprawl::threading::CoroutineBase::Type()
{
	return m_holder->Type();
}
# Change User Description Committed
#2 18645 brandon_m_bare Integrated latest version of libsprawl.
#1 15089 brandon_m_bare First integration of sprawl.
//guest/ShadauxCat/Sprawl/Mainline/threading/coroutine.cpp
#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 14115 ShadauxCat Add missing copy/move/assignment/destructor for BitVector, variadic constructor for Coroutine

#review-14116
#1 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