Revert "Work in progress"

This reverts commit ef35aa7954
because it contained too much wrong things that I won't be
using. I'll re-commit stuff from it after that that I do
want to keep.
This commit is contained in:
Aleric Inglewood
2013-02-23 20:00:13 +01:00
parent ef35aa7954
commit 4851cc174e
14 changed files with 75 additions and 235 deletions

View File

@@ -82,8 +82,7 @@ void AIStateMachine::setMaxCount(F32 StateMachineMaxTime)
void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bool abort_parent, bool on_abort_signal_parent)
{
DoutEntering(dc::statemachine, "AIStateMachine::run(" << (void*)parent << ", " << (parent ? parent->state_str(new_parent_state) : "NA") <<
", " << abort_parent << ", " << on_abort_signal_parent << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine, "AIStateMachine::run(" << (void*)parent << ", " << (parent ? parent->state_str(new_parent_state) : "NA") << ", " << abort_parent << ") [" << (void*)this << "]");
// Must be the first time we're being run, or we must be called from a callback function.
llassert(!mParent || mState == bs_callback);
llassert(!mCallback || mState == bs_callback);
@@ -114,7 +113,7 @@ void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bo
// Mark that run() has been called, in case we're being called from a callback function.
mState = bs_initialize;
// Set mIdle to false and add statemachine to continued_statemachines-- or, when boosted, run the statemachine till it finished or goes idle.
// Set mIdle to false and add statemachine to continued_statemachines.
mSetStateLock.lock();
locked_cont();
}
@@ -141,7 +140,7 @@ void AIStateMachine::run(callback_type::signal_type::slot_type const& slot)
// Mark that run() has been called, in case we're being called from a callback function.
mState = bs_initialize;
// Set mIdle to false and add statemachine to continued_statemachines-- or, when boosted, run the statemachine till it finished or goes idle.
// Set mIdle to false and add statemachine to continued_statemachines.
mSetStateLock.lock();
locked_cont();
}
@@ -149,11 +148,9 @@ void AIStateMachine::run(callback_type::signal_type::slot_type const& slot)
void AIStateMachine::idle(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::idle() [" << (void*)this << "]");
llassert(mInsideMultiplexImpl);
mSetStateLock.lock();
llassert(is_main_thread());
llassert(!mIdle);
mIdle = true;
mSetStateLock.unlock();
mSleep = 0;
#ifdef SHOW_ASSERT
mCalledThreadUnsafeIdle = true;
@@ -163,12 +160,9 @@ void AIStateMachine::idle(void)
void AIStateMachine::idle(state_type current_run_state)
{
DoutEntering(dc::statemachine, "AIStateMachine::idle(" << state_str(current_run_state) << ") [" << (void*)this << "]");
llassert(mInsideMultiplexImpl); // Only boosted state machines can come here as non-main thread because you may only get here from multiplex_impl().
mSetStateLock.lock();
// If two different threads call multiplex_impl() (boosted state machines) then that should happen serialized:
// only one thread may call multiplex() at any given time. Hence, it is impossible that idle() is called while
// we are already idle.
llassert(is_main_thread());
llassert(!mIdle);
mSetStateLock.lock();
// Only go idle if the run state is (still) what we expect it to be.
// Otherwise assume that another thread called set_state() and continue running.
if (current_run_state == mRunState)
@@ -202,7 +196,6 @@ void AIStateMachine::locked_cont(void)
mIdle = false;
bool not_active = mActive == as_idle;
mIdleActive.unlock();
mBoost = thread_safe_impl();
// mActive is only changed in AIStateMachine::mainloop, by the main-thread, and
// here, possibly by any thread. However, after setting mIdle to false above, it
// is impossible for any thread to come here, until after the main-thread called
@@ -217,15 +210,8 @@ void AIStateMachine::locked_cont(void)
// to release mSetStateLock here, with as advantage that if we're not the main-
// thread and not_active is true, then the main-thread won't block when it has
// a timer running that times out and calls set_state().
// Finally, if mBoost is true then not_active is not going to be tested and
// mActive is not going to be changed, so then we're done with this lock too.
mSetStateLock.unlock();
if (mBoost)
{
// Run statemachine until it is finished or idle again.
multiplex(0);
}
else if (not_active)
if (not_active)
{
AIWriteAccess<csme_type> csme_w(sContinuedStateMachinesAndMainloopEnabled);
// See above: it is not possible that mActive was changed since not_active
@@ -250,6 +236,9 @@ void AIStateMachine::set_state(state_type state)
// Stop race condition of multiple threads calling cont() or set_state() here.
mSetStateLock.lock();
// Do not call set_state() unless running.
llassert(mState == bs_run || !is_main_thread());
// If this function is called from another thread than the main thread, then we have to ignore
// it if we're not idle and the state is less than the current state. The main thread must
// be able to change the state to anything (also smaller values). Note that that only can work
@@ -290,11 +279,8 @@ void AIStateMachine::set_state(state_type state)
return; // Ignore.
}
// Do not call set_state() from multiplex_impl unless running.
llassert(mState == bs_run || !mInsideMultiplexImpl);
// Do not call idle() when set_state is called from another thread; use idle(state_type) instead.
llassert(!mCalledThreadUnsafeIdle || AIThreadID::in_main_thread());
llassert(!mCalledThreadUnsafeIdle || is_main_thread());
// Change mRunState to the requested value.
if (mRunState != state)
@@ -307,15 +293,7 @@ void AIStateMachine::set_state(state_type state)
if (mIdle)
locked_cont(); // This unlocks mSetStateLock.
else
{
// The state was changed while not being idle.
// Note that if thread_safe_impl() returns true now then we don't need to call multiplex() here
// when we ended up here from multiplex(). However, if we end up here as the result of an
// external state change while the state machine is running in the main thread, then we can't
// call multiplex here; it would be too dangerous. In that case we let the main thread pick
// up this state.
mSetStateLock.unlock();
}
// If we get here then mIdle is false, so only mRunState can still be changed but we won't
// call locked_cont() anymore. When the main thread finally picks up on the state change,
@@ -476,7 +454,6 @@ void AIStateMachine::multiplex(U64 current_time)
// amount of time has passed.
if (mSleep != 0)
{
llassert(!mBoost); // Sleeping MUST be done in the main thread: thread_safe_impl() should have returned false.
if (mSleep < 0)
{
if (++mSleep)
@@ -498,90 +475,11 @@ void AIStateMachine::multiplex(U64 current_time)
{
mAborted = false;
mState = bs_run;
#ifdef SHOW_ASSERT
mInsideMultiplexImpl = true;
#endif
initialize_impl();
#ifdef SHOW_ASSERT
mInsideMultiplexImpl = false;
#endif
if (mAborted || mState != bs_run)
{
mBoost = false;
return;
}
mSetStateLock.lock();
mBoost = thread_safe_impl();
if (!mBoost && !AIThreadID::in_main_thread())
{
// Pass running on the main thread.
mIdle = true;
locked_cont();
return;
}
mSetStateLock.unlock();
}
if (!mBoost)
{
llassert(AIThreadID::in_main_thread());
#ifdef SHOW_ASSERT
mInsideMultiplexImpl = true;
#endif
multiplex_impl();
#ifdef SHOW_ASSERT
mInsideMultiplexImpl = false;
#endif
}
else
{
if (mState != bs_run)
return;
mSetStateLock.lock();
llassert(!mIdle); // We should never get here when idle.
if (!mMultiplexMutex.tryLock()) // Point A
{
// If another thread is already already calling multiplex_impl() then we can't do that too.
// However, instead of blocking we simply return: by getting here it is guaranteed that
// the other thread will do at least one more test of 'mState == bs_run && !mIdle' before
// stopping to run the statemachine.
// The reason for that is that if another thread had mMultiplexMutex at point A, while
// we had mSetStateLock, then the other thread has to be between point B and point C
// because that is the only area where mSetStateLock is unlocked while mMultiplexMutex
// is locked, and the test follows this area.
mSetStateLock.unlock();
return;
}
do
{
mSetStateLock.unlock(); // Point B
#ifdef SHOW_ASSERT
mInsideMultiplexImpl = true;
#endif
multiplex_impl();
#ifdef SHOW_ASSERT
mInsideMultiplexImpl = false;
#endif
mSetStateLock.lock(); // Point C
// The state might have changed, check if we may still run outside the main thread.
mBoost = thread_safe_impl();
if (!mBoost && !AIThreadID::in_main_thread())
{
mMultiplexMutex.unlock();
// Pass running on the main thread.
mIdle = true;
locked_cont();
return;
}
}
while (mState == bs_run && !mIdle);
mMultiplexMutex.unlock();
mSetStateLock.unlock();
}
multiplex_impl();
}
//static
@@ -692,10 +590,6 @@ void AIStateMachine::flush(void)
for (active_statemachines_type::iterator iter = active_statemachines.begin(); iter != active_statemachines.end(); ++iter)
{
AIStateMachine& statemachine(iter->statemachine());
#ifdef SHOW_ASSERT
// Make assertions happy.
statemachine.mInsideMultiplexImpl = true;
#endif
if (statemachine.abortable())
{
// We can't safely call abort() here for non-running (run() was called, but they weren't initialized yet) statemachines,