Add AIStateMachine::mSMDebug

The patch is exclusively libcwd related.

Turns off output from statemachines to dc::statemachine by default.
Allows to turn on the debug output on a per statemachine basis (at
compile time).
This commit is contained in:
Aleric Inglewood
2013-10-15 21:22:18 +02:00
parent aa077032b7
commit 9db6bc0557
12 changed files with 83 additions and 48 deletions

View File

@@ -283,7 +283,7 @@ char const* HelloWorld::state_str_impl(state_type run_state) const
void AIEngine::add(AIStateMachine* state_machine)
{
Dout(dc::statemachine, "Adding state machine [" << (void*)state_machine << "] to " << mName);
Dout(dc::statemachine(state_machine->mSMDebug), "Adding state machine [" << (void*)state_machine << "] to " << mName);
engine_state_type_wat engine_state_w(mEngineState);
engine_state_w->list.push_back(QueueElement(state_machine));
if (engine_state_w->waiting)
@@ -330,7 +330,7 @@ void AIEngine::mainloop(void)
engine_state_type_wat engine_state_w(mEngineState);
if (!active)
{
Dout(dc::statemachine, "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
Dout(dc::statemachine(state_machine.mSMDebug), "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
engine_state_w->list.erase(queued_element++);
}
else
@@ -392,7 +392,7 @@ void AIStateMachine::multiplex(event_type event)
// If this fails then you are using a pointer to a state machine instead of an LLPointer.
llassert(event == initial_run || getNumRefs() > 0);
DoutEntering(dc::statemachine, "AIStateMachine::multiplex(" << event_str(event) << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::multiplex(" << event_str(event) << ") [" << (void*)this << "]");
base_state_type state;
state_type run_state;
@@ -407,7 +407,7 @@ void AIStateMachine::multiplex(event_type event)
llassert(!mMultiplexMutex.isSelfLocked()); // We may never enter recursively!
if (!mMultiplexMutex.tryLock())
{
Dout(dc::statemachine, "Leaving because it is already being run [" << (void*)this << "]");
Dout(dc::statemachine(mSMDebug), "Leaving because it is already being run [" << (void*)this << "]");
return;
}
@@ -421,7 +421,7 @@ void AIStateMachine::multiplex(event_type event)
// we should indeed run, again.
if (event == schedule_run && !sub_state_type_rat(mSubState)->need_run)
{
Dout(dc::statemachine, "Leaving because it was already being run [" << (void*)this << "]");
Dout(dc::statemachine(mSMDebug), "Leaving because it was already being run [" << (void*)this << "]");
return;
}
@@ -440,9 +440,9 @@ void AIStateMachine::multiplex(event_type event)
{
#ifdef CWDEBUG
if (state == bs_multiplex)
Dout(dc::statemachine, "Running state bs_multiplex / " << state_str_impl(run_state) << " [" << (void*)this << "]");
Dout(dc::statemachine(mSMDebug), "Running state bs_multiplex / " << state_str_impl(run_state) << " [" << (void*)this << "]");
else
Dout(dc::statemachine, "Running state " << state_str(state) << " [" << (void*)this << "]");
Dout(dc::statemachine(mSMDebug), "Running state " << state_str(state) << " [" << (void*)this << "]");
#endif
#ifdef SHOW_ASSERT
@@ -503,7 +503,7 @@ void AIStateMachine::multiplex(event_type event)
// run of bs_reset is not a problem because it happens to be a NoOp.
state = (state == bs_initialize) ? bs_reset : bs_abort;
#ifdef CWDEBUG
Dout(dc::statemachine, "Late abort detected! Running state " << state_str(state) << " instead [" << (void*)this << "]");
Dout(dc::statemachine(mSMDebug), "Late abort detected! Running state " << state_str(state) << " instead [" << (void*)this << "]");
#endif
}
#ifdef SHOW_ASSERT
@@ -665,7 +665,7 @@ void AIStateMachine::multiplex(event_type event)
#ifdef CWDEBUG
if (state != state_w->base_state)
Dout(dc::statemachine, "Base state changed from " << state_str(state) << " to " << state_str(state_w->base_state) <<
Dout(dc::statemachine(mSMDebug), "Base state changed from " << state_str(state) << " to " << state_str(state_w->base_state) <<
"; need_new_run = " << (need_new_run ? "true" : "false") << " [" << (void*)this << "]");
#endif
}
@@ -702,8 +702,8 @@ void AIStateMachine::multiplex(event_type event)
}
else
{
// Remove this state machine from any engine.
// Cause the engine to remove us.
// Remove this state machine from any engine,
// causing the engine to remove us.
state_w->current_engine = NULL;
}
@@ -749,7 +749,7 @@ void AIStateMachine::multiplex(event_type event)
AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state)
{
DoutEntering(dc::statemachine, "AIStateMachine::begin_loop(" << state_str(base_state) << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::begin_loop(" << state_str(base_state) << ") [" << (void*)this << "]");
sub_state_type_wat sub_state_w(mSubState);
// Honor a subsequent call to idle() (only necessary in bs_multiplex, but it doesn't hurt to reset this flag in other states too).
@@ -759,7 +759,7 @@ AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state
// Honor previous calls to advance_state() (once run_state is initialized).
if (base_state == bs_multiplex && sub_state_w->advance_state > sub_state_w->run_state)
{
Dout(dc::statemachine, "Copying advance_state to run_state, because it is larger [" << state_str_impl(sub_state_w->advance_state) << " > " << state_str_impl(sub_state_w->run_state) << "]");
Dout(dc::statemachine(mSMDebug), "Copying advance_state to run_state, because it is larger [" << state_str_impl(sub_state_w->advance_state) << " > " << state_str_impl(sub_state_w->run_state) << "]");
sub_state_w->run_state = sub_state_w->advance_state;
}
#ifdef SHOW_ASSERT
@@ -789,7 +789,7 @@ AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state
void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bool abort_parent, bool on_abort_signal_parent, AIEngine* default_engine)
{
DoutEntering(dc::statemachine, "AIStateMachine::run(" <<
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::run(" <<
(void*)parent << ", " <<
(parent ? parent->state_str_impl(new_parent_state) : "NA") <<
", abort_parent = " << (abort_parent ? "true" : "false") <<
@@ -839,7 +839,7 @@ void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bo
void AIStateMachine::run(callback_type::signal_type::slot_type const& slot, AIEngine* default_engine)
{
DoutEntering(dc::statemachine, "AIStateMachine::run(<slot>, default_engine = " << default_engine->name() << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::run(<slot>, default_engine = " << default_engine->name() << ") [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
@@ -874,7 +874,7 @@ void AIStateMachine::run(callback_type::signal_type::slot_type const& slot, AIEn
void AIStateMachine::callback(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::callback() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::callback() [" << (void*)this << "]");
bool aborted = sub_state_type_rat(mSubState)->aborted;
if (mParent)
@@ -920,7 +920,7 @@ void AIStateMachine::force_killed(void)
void AIStateMachine::kill(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::kill() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::kill() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -937,7 +937,7 @@ void AIStateMachine::kill(void)
void AIStateMachine::reset()
{
DoutEntering(dc::statemachine, "AIStateMachine::reset() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::reset() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
mDebugAborted = false;
mDebugContPending = false;
@@ -972,7 +972,7 @@ void AIStateMachine::reset()
void AIStateMachine::set_state(state_type new_state)
{
DoutEntering(dc::statemachine, "AIStateMachine::set_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::set_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -999,13 +999,13 @@ void AIStateMachine::set_state(state_type new_state)
void AIStateMachine::advance_state(state_type new_state)
{
DoutEntering(dc::statemachine, "AIStateMachine::advance_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::advance_state(" << state_str_impl(new_state) << ") [" << (void*)this << "]");
{
sub_state_type_wat sub_state_w(mSubState);
// Ignore call to advance_state when the currently queued state is already greater or equal to the requested state.
if (sub_state_w->advance_state >= new_state)
{
Dout(dc::statemachine, "Ignored, because " << state_str_impl(sub_state_w->advance_state) << " >= " << state_str_impl(new_state) << ".");
Dout(dc::statemachine(mSMDebug), "Ignored, because " << state_str_impl(sub_state_w->advance_state) << " >= " << state_str_impl(new_state) << ".");
return;
}
// Ignore call to advance_state when the current state is greater than the requested state: the new state would be
@@ -1014,7 +1014,7 @@ void AIStateMachine::advance_state(state_type new_state)
// the state change is and should be being ignored: the statemachine would start running it's current state (again).
if (sub_state_w->run_state > new_state)
{
Dout(dc::statemachine, "Ignored, because " << state_str_impl(sub_state_w->run_state) << " > " << state_str_impl(new_state) << " (current state).");
Dout(dc::statemachine(mSMDebug), "Ignored, because " << state_str_impl(sub_state_w->run_state) << " > " << state_str_impl(new_state) << " (current state).");
return;
}
// Increment state.
@@ -1048,7 +1048,7 @@ void AIStateMachine::advance_state(state_type new_state)
void AIStateMachine::idle(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::idle() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::idle() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -1066,7 +1066,7 @@ void AIStateMachine::idle(void)
// Ignore call to idle() when advance_state() was called since last call to set_state().
if (sub_state_w->skip_idle)
{
Dout(dc::statemachine, "Ignored, because skip_idle is true (advance_state() was called last).");
Dout(dc::statemachine(mSMDebug), "Ignored, because skip_idle is true (advance_state() was called last).");
return;
}
// Mark that we are idle.
@@ -1077,7 +1077,7 @@ void AIStateMachine::idle(void)
void AIStateMachine::cont(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::cont() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::cont() [" << (void*)this << "]");
{
sub_state_type_wat sub_state_w(mSubState);
// Void last call to idle(), if any.
@@ -1097,7 +1097,7 @@ void AIStateMachine::cont(void)
void AIStateMachine::abort(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::abort() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::abort() [" << (void*)this << "]");
bool is_waiting = false;
{
multiplex_state_type_rat state_r(mState);
@@ -1128,7 +1128,7 @@ void AIStateMachine::abort(void)
void AIStateMachine::finish(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::finish() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::finish() [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -1147,7 +1147,7 @@ void AIStateMachine::finish(void)
void AIStateMachine::yield(void)
{
DoutEntering(dc::statemachine, "AIStateMachine::yield() [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield() [" << (void*)this << "]");
multiplex_state_type_rat state_r(mState);
// yield() may only be called from multiplex_impl().
llassert(state_r->base_state == bs_multiplex);
@@ -1160,7 +1160,7 @@ void AIStateMachine::yield(void)
void AIStateMachine::yield(AIEngine* engine)
{
llassert(engine);
DoutEntering(dc::statemachine, "AIStateMachine::yield(" << engine->name() << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield(" << engine->name() << ") [" << (void*)this << "]");
#ifdef SHOW_ASSERT
{
multiplex_state_type_rat state_r(mState);
@@ -1175,7 +1175,7 @@ void AIStateMachine::yield(AIEngine* engine)
void AIStateMachine::yield_frame(unsigned int frames)
{
DoutEntering(dc::statemachine, "AIStateMachine::yield_frame(" << frames << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield_frame(" << frames << ") [" << (void*)this << "]");
mSleep = -(S64)frames;
// Sleeping is always done from the main thread.
yield(&gMainThreadEngine);
@@ -1183,7 +1183,7 @@ void AIStateMachine::yield_frame(unsigned int frames)
void AIStateMachine::yield_ms(unsigned int ms)
{
DoutEntering(dc::statemachine, "AIStateMachine::yield_ms(" << ms << ") [" << (void*)this << "]");
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::yield_ms(" << ms << ") [" << (void*)this << "]");
mSleep = get_clock_count() + calc_clock_frequency() * ms / 1000;
// Sleeping is always done from the main thread.
yield(&gMainThreadEngine);
@@ -1233,7 +1233,7 @@ void AIEngine::threadloop(void)
engine_state_type_wat engine_state_w(mEngineState);
if (!active)
{
Dout(dc::statemachine, "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
Dout(dc::statemachine(state_machine.mSMDebug), "Erasing state machine [" << (void*)&state_machine << "] from " << mName);
engine_state_w->list.erase(queued_element++);
}
else

View File

@@ -195,13 +195,21 @@ class AIStateMachine : public LLThreadSafeRefCount
bool mDebugAdvanceStatePending; // True while advance_state() was called by not handled yet.
bool mDebugRefCalled; // True when ref() is called (or will be called within the critial area of mMultiplexMutex).
#endif
#ifdef CWDEBUG
protected:
bool mSMDebug; // Print debug output only when true.
#endif
private:
U64 mRuntime; // Total time spent running in the main thread (in clocks).
public:
AIStateMachine(void) : mCallback(NULL), mDefaultEngine(NULL), mYieldEngine(NULL),
AIStateMachine(CWD_ONLY(bool debug)) : mCallback(NULL), mDefaultEngine(NULL), mYieldEngine(NULL),
#ifdef SHOW_ASSERT
mThreadId(AIThreadID::none), mDebugLastState(bs_killed), mDebugShouldRun(false), mDebugAborted(false), mDebugContPending(false),
mDebugSetStatePending(false), mDebugAdvanceStatePending(false), mDebugRefCalled(false),
#endif
#ifdef CWDEBUG
mSMDebug(debug),
#endif
mRuntime(0)
{ }

View File

@@ -181,7 +181,11 @@ class AIStateMachineThreadBase : public AIStateMachine {
static state_type const max_state = wait_stopped + 1;
protected:
AIStateMachineThreadBase(void) { }
AIStateMachineThreadBase(CWD_ONLY(bool debug))
#ifdef CWDEBUG
: AIStateMachine(debug)
#endif
{ }
private:
// Handle initializing the object.
@@ -217,7 +221,10 @@ class AIStateMachineThread : public AIStateMachineThreadBase {
public:
// Constructor.
AIStateMachineThread(void)
AIStateMachineThread(CWD_ONLY(bool debug))
#ifdef CWDEBUG
: AIStateMachineThreadBase(debug)
#endif
{
*AIThreadImpl::StateMachineThread_wat(mThreadImpl.mStateMachineThread) = this;
}

View File

@@ -76,7 +76,11 @@ class AITimer : public AIStateMachine {
F64 mInterval; //!< Input variable: interval after which the event will be generated, in seconds.
public:
AITimer(void) : mInterval(0) { DoutEntering(dc::statemachine, "AITimer(void) [" << (void*)this << "]"); }
AITimer(CWD_ONLY(bool debug = false)) :
#ifdef CWDEBUG
AIStateMachine(debug),
#endif
mInterval(0) { DoutEntering(dc::statemachine(mSMDebug), "AITimer(void) [" << (void*)this << "]"); }
/**
* @brief Set the interval after which the timer should expire.
@@ -96,7 +100,7 @@ class AITimer : public AIStateMachine {
protected:
// Call finish() (or abort()), not delete.
/*virtual*/ ~AITimer() { DoutEntering(dc::statemachine, "~AITimer() [" << (void*)this << "]"); mFrameTimer.cancel(); }
/*virtual*/ ~AITimer() { DoutEntering(dc::statemachine(mSMDebug), "~AITimer() [" << (void*)this << "]"); mFrameTimer.cancel(); }
// Handle initializing the object.
/*virtual*/ void initialize_impl(void);

View File

@@ -144,6 +144,7 @@ extern LL_COMMON_API fake_channel const snapshot;
#define CWDEBUG_MARKER 0
#define BACKTRACE do { } while(0)
#define CWD_ONLY(...)
#endif // !DOXYGEN
@@ -180,6 +181,7 @@ extern LL_COMMON_API fake_channel const snapshot;
#include <set>
#define CWD_API __attribute__ ((visibility("default")))
#define CWD_ONLY(...) __VA_ARGS__
//! Debug specific code.
namespace debug {

View File

@@ -250,10 +250,13 @@ void AICurlEasyRequestStateMachine::finish_impl(void)
}
}
AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(void) :
AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(CWD_ONLY(bool debug)) :
#ifdef CWDEBUG
AIStateMachine(debug),
#endif
mTotalDelayTimeout(AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout().getTotalDelay())
{
Dout(dc::statemachine, "Calling AICurlEasyRequestStateMachine(void) [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
Dout(dc::statemachine(mSMDebug), "Calling AICurlEasyRequestStateMachine(void) [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
AICurlInterface::Stats::AICurlEasyRequestStateMachine_count++;
}
@@ -264,7 +267,7 @@ void AICurlEasyRequestStateMachine::setTotalDelayTimeout(F32 totalDelayTimeout)
AICurlEasyRequestStateMachine::~AICurlEasyRequestStateMachine()
{
Dout(dc::statemachine, "Calling ~AICurlEasyRequestStateMachine() [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
Dout(dc::statemachine(mSMDebug), "Calling ~AICurlEasyRequestStateMachine() [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
--AICurlInterface::Stats::AICurlEasyRequestStateMachine_count;
}

View File

@@ -52,7 +52,7 @@
// Construction of a AICurlEasyRequestStateMachine might throw AICurlNoEasyHandle.
class AICurlEasyRequestStateMachine : public AIStateMachine, public AICurlEasyHandleEvents {
public:
AICurlEasyRequestStateMachine(void);
AICurlEasyRequestStateMachine(CWD_ONLY(bool debug = false));
// Transparent access.
AICurlEasyRequest mCurlEasyRequest;

View File

@@ -1414,7 +1414,10 @@ void LLMeshUploadThread::preStart()
AIMeshUpload::AIMeshUpload(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, std::string const& upload_url, bool do_upload,
LLHandle<LLWholeModelFeeObserver> const& fee_observer, LLHandle<LLWholeModelUploadObserver> const& upload_observer) :
mMeshUpload(new AIStateMachineThread<LLMeshUploadThread>), mWholeModelUploadURL(upload_url)
#ifdef CWDEBUG
AIStateMachine(false),
#endif
mMeshUpload(new AIStateMachineThread<LLMeshUploadThread>(CWD_ONLY(false))), mWholeModelUploadURL(upload_url)
{
mMeshUpload->thread_impl().init(data, scale, upload_textures, upload_skin, upload_joints, do_upload, fee_observer, upload_observer);
}

View File

@@ -155,7 +155,7 @@ void AIFetchInventoryFolder::multiplex_impl(state_type run_state)
// Create the folder.
mFolderUUID = gInventory.createNewCategory(mParentFolder, LLFolderType::FT_NONE, mFolderName);
llassert_always(!mFolderUUID.isNull());
Dout(dc::statemachine, "Created folder \"" << mFolderName << "\".");
Dout(dc::statemachine(mSMDebug), "Created folder \"" << mFolderName << "\".");
mNeedNotifyObservers = true;
}
mCreated = true;

View File

@@ -58,8 +58,12 @@ class AIFetchInventoryFolder : public AIStateMachine {
bool mNeedNotifyObservers;
public:
AIFetchInventoryFolder(void) : mCreate(false), mFetchContents(false), mExists(false), mCreated(false)
{ Dout(dc::statemachine, "Calling AIFetchInventoryFolder constructor [" << (void*)this << "]"); }
AIFetchInventoryFolder(CWD_ONLY(bool debug = false)) :
#ifdef CWDEBUG
AIStateMachine(debug),
#endif
mCreate(false), mFetchContents(false), mExists(false), mCreated(false)
{ Dout(dc::statemachine(mSMDebug), "Calling AIFetchInventoryFolder constructor [" << (void*)this << "]"); }
/**
* @brief Fetch an inventory folder by name, optionally creating it.
@@ -132,7 +136,7 @@ class AIFetchInventoryFolder : public AIStateMachine {
protected:
// Call finish() (or abort()), not delete.
/*virtual*/ ~AIFetchInventoryFolder() { Dout(dc::statemachine, "Calling ~AIFetchInventoryFolder() [" << (void*)this << "]"); }
/*virtual*/ ~AIFetchInventoryFolder() { Dout(dc::statemachine(mSMDebug), "Calling ~AIFetchInventoryFolder() [" << (void*)this << "]"); }
// Handle initializing the object.
/*virtual*/ void initialize_impl(void);

View File

@@ -60,7 +60,11 @@ char const* AIFilePicker::state_str_impl(state_type run_state) const
return "UNKNOWN STATE";
}
AIFilePicker::AIFilePicker(void) : mPluginManager(NULL), mCanceled(false)
AIFilePicker::AIFilePicker(CWD_ONLY(bool debug)) :
#ifdef CWDEBUG
AIStateMachine(debug),
#endif
mPluginManager(NULL), mCanceled(false)
{
}

View File

@@ -168,7 +168,7 @@ public:
public:
// The derived class must have a default constructor.
AIFilePicker(void);
AIFilePicker(CWD_ONLY(bool debug = false));
// Create a dynamically created AIFilePicker object.
static AIFilePicker* create(void) { AIFilePicker* filepicker = new AIFilePicker; return filepicker; }