Skip to content

Commit

Permalink
Fixed problem with unlabelled timers firing out of sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgammon committed Mar 22, 2016
1 parent c0c8f99 commit d5ff964
Show file tree
Hide file tree
Showing 17 changed files with 221 additions and 183 deletions.
12 changes: 10 additions & 2 deletions OtherTypes.h
Expand Up @@ -633,7 +633,6 @@ class CTimer : public CObject
bOmitFromOutput = false;
bOmitFromLog = false;
bExecutingScript = false;

};

bool operator== (const CTimer & rhs) const;
Expand Down Expand Up @@ -686,6 +685,8 @@ class CTimer : public CObject
long nInvocationCount; // how many times procedure called
long nMatched; // how many times the timer fired

unsigned long nCreateSequence; // for keeping timers in sequence of creation

// calculated field - when timer is next to go off (fire)

CmcDateTime tFireTime; // when to fire it
Expand All @@ -695,9 +696,16 @@ class CTimer : public CObject
bool bSelected; // if true, selected for use in a plugin
bool bExecutingScript; // if true, executing a script and cannot be deleted

static unsigned long GetNextTimerSequence () { return nNextCreateSequence++; }

private:
static unsigned long nNextCreateSequence;

};

typedef CTypedPtrMap <CMapStringToPtr, CString, CTimer*> CTimerMap;
typedef map <string, CTimer*> CTimerMap;
typedef CTimerMap::iterator CTimerMapIterator;

// map for lookup name from pointer
typedef map <CTimer*, string> CTimerRevMap;

Expand Down
35 changes: 17 additions & 18 deletions dialogs/plugins/PluginWizard.cpp
Expand Up @@ -586,13 +586,12 @@ BOOL CPluginWizardPage5::OnInitDialog()
m_ctlList.InsertColumn(3, TranslateHeading ("Group"), LVCFMT_LEFT, 50);

int iItem = 0;
POSITION pos;
CString strName;

for (pos = m_doc->m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_doc->m_TimerMap.begin ();
timerIt != m_doc->m_TimerMap.end ();
timerIt++)
{
CTimer * t;
m_doc->m_TimerMap.GetNextAssoc (pos, strName, t);
CTimer * t = timerIt->second;

if (t->bTemporary)
continue; // ignore temporary ones
Expand Down Expand Up @@ -643,14 +642,13 @@ void CPluginWizardPage5::OnSelectNone()

void CPluginWizardPage5::OnOK()
{
POSITION pos;
CString strName;

// first deselect everything
for (pos = m_doc->m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_doc->m_TimerMap.begin ();
timerIt != m_doc->m_TimerMap.end ();
timerIt++)
{
CTimer * t;
m_doc->m_TimerMap.GetNextAssoc (pos, strName, t);
CTimer * t = timerIt->second;
t->bSelected = false;
}

Expand All @@ -659,15 +657,16 @@ void CPluginWizardPage5::OnOK()
{
CTimer * t = (CTimer *) m_ctlList.GetItemData (nItem);
// find in Timer array (in case it doesn't exist any more) and select it
for (pos = m_doc->m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_doc->m_TimerMap.begin ();
timerIt != m_doc->m_TimerMap.end ();
timerIt++)
{
CTimer * t2;
m_doc->m_TimerMap.GetNextAssoc (pos, strName, t2);
if (t == t2)
{
t->bSelected = true;
break;
}
CTimer * t2 = timerIt->second;
if (t == t2)
{
t->bSelected = true;
break;
}
}
} // end of each list item

Expand Down
8 changes: 4 additions & 4 deletions dialogs/world_prefs/TimerDlg.cpp
Expand Up @@ -142,13 +142,13 @@ void CTimerDlg::DoDataExchange(CDataExchange* pDX)
} // end of doing a periodical timer


CString strTimerName;
CTimer * timer_item;
POSITION pos;

for (pos = m_pTimerMap->GetStartPosition (); pos; )
for (CTimerMapIterator timerIt = m_pTimerMap->begin ();
timerIt != m_pTimerMap->end ();
timerIt++)
{
m_pTimerMap->GetNextAssoc (pos, strTimerName, timer_item);
timer_item = timerIt->second;

// don't compare against itself

Expand Down
10 changes: 5 additions & 5 deletions dialogs/world_prefs/configuration.cpp
Expand Up @@ -441,7 +441,6 @@ void CMUSHclientDoc:: LoadPrefsP15 (CPrefsP15 &page15)

CTrigger * pTrigger;
CAlias * pAlias;
CTimer * pTimer;
CString strName;
POSITION pos;
LONGLONG iTimeTaken = 0;
Expand All @@ -466,10 +465,11 @@ void CMUSHclientDoc:: LoadPrefsP15 (CPrefsP15 &page15)
}

// count number of timers fired
for (pos = m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
timerIt++)
{
m_TimerMap.GetNextAssoc (pos, strName, pTimer);
nTotalTimers += pTimer->nMatched;
nTotalTimers += timerIt->second->nMatched;
}

page15.m_strBufferLines.Format ("%i / %ld",
Expand Down Expand Up @@ -500,7 +500,7 @@ void CMUSHclientDoc:: LoadPrefsP15 (CPrefsP15 &page15)
m_AliasMap.GetCount (),
nTotalAliases);
page15.m_strTimers.Format ("%i (%I64d fired)",
m_TimerMap.GetCount (),
m_TimerMap.size (),
nTotalTimers);

if (m_sockAddr.sin_addr.s_addr == INADDR_NONE)
Expand Down
4 changes: 2 additions & 2 deletions dialogs/world_prefs/prefspropertypages.cpp
Expand Up @@ -6203,10 +6203,10 @@ void CPrefsP16::DoDataExchange(CDataExchange* pDX)
if (pDX->m_bSaveAndValidate)
if (m_ctlUseDefaultTimers.GetCheck ())
if (m_ctlUseDefaultTimers.GetCheck () != m_bUseDefaultTimers)
if (m_doc->m_TimerMap.GetCount () > 0)
if (m_doc->m_TimerMap.size () > 0)
if (::UMessageBox (TFormat ("By checking the option \"Override with default timers\" "
" your existing %i timer%s will be PERMANENTLY discarded next time you open this world.\n\n"
"Are you SURE you want to do this?", PLURAL (m_doc->m_TimerMap.GetCount ())),
"Are you SURE you want to do this?", PLURAL (m_doc->m_TimerMap.size ())),
MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 ) != IDYES)
pDX->Fail ();

Expand Down
11 changes: 8 additions & 3 deletions doc_construct.cpp
Expand Up @@ -39,7 +39,6 @@ int i;
m_VariableMap.InitHashTable (997); // allow for 1000 variables (at least)
m_AliasMap.InitHashTable (293); // probably won't have many more than 300 aliases
m_TriggerMap.InitHashTable (293); // probably won't have many more than 300 triggers
m_TimerMap.InitHashTable (293); // probably won't have many more than 300 timers

SetDefaults (false); // set up numeric/boolean defaults
SetAlphaDefaults (false); // set up alpha defaults
Expand Down Expand Up @@ -561,8 +560,14 @@ int i;

// delete timer map

DELETE_MAP (m_TimerMap, CTimer);

for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
timerIt++)
delete timerIt->second;
m_TimerMap.clear ();
m_TimerRevMap.clear ();


// delete variables map

DELETE_MAP (m_VariableMap, CVariable);
Expand Down
11 changes: 9 additions & 2 deletions evaluate.cpp
Expand Up @@ -613,7 +613,7 @@ if (strFileName.IsEmpty ())
replace = FALSE;
}
else
if (set_type == TIMER && !m_TimerMap.IsEmpty ())
if (set_type == TIMER && !m_TimerMap.empty ())
{
if (::TMessageBox ("Replace existing timers?\n"
"If you reply \"No\", then timers from the file"
Expand Down Expand Up @@ -661,7 +661,14 @@ CArchive * ar = NULL;

case TIMER:
if (replace)
DELETE_MAP (m_TimerMap, CTimer);
{
for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
timerIt++)
delete timerIt->second;
m_TimerMap.clear ();
m_TimerRevMap.clear ();
}
Load_World_XML (*ar, XML_TIMERS | XML_NO_PLUGINS | XML_IMPORT_MAIN_FILE_ONLY);
break;

Expand Down
44 changes: 25 additions & 19 deletions plugins.cpp
Expand Up @@ -159,7 +159,6 @@ CPlugin::CPlugin (CMUSHclientDoc * pDoc)
m_VariableMap.InitHashTable (293); // allow for 300 variables in this plugin
m_AliasMap.InitHashTable (293); // ditto for aliases
m_TriggerMap.InitHashTable (293); // ditto for triggers
m_TimerMap.InitHashTable (293); // ditto for timers
m_tDateInstalled = CTime::GetCurrentTime(); // when plugin loaded

m_dRequiredVersion = 0.0;
Expand All @@ -186,7 +185,12 @@ CPlugin::~CPlugin ()
SaveState ();
DELETE_MAP (m_TriggerMap, CTrigger);
DELETE_MAP (m_AliasMap, CAlias);
DELETE_MAP (m_TimerMap, CTimer);
for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
timerIt++)
delete timerIt->second;
m_TimerMap.clear ();
m_TimerRevMap.clear ();
DELETE_MAP (m_VariableMap, CVariable);
delete m_ScriptEngine;

Expand Down Expand Up @@ -907,11 +911,11 @@ void CMUSHclientDoc::OnFilePluginwizard()
a->bSelected = true;
}
// timers
for (pos = m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
timerIt++)
{
CTimer * t;
m_TimerMap.GetNextAssoc (pos, strName, t);
t->bSelected = true;
timerIt->second->bSelected = true;
}
// variables
for (pos = m_VariableMap.GetStartPosition(); pos; iCount++)
Expand Down Expand Up @@ -1122,24 +1126,24 @@ void CMUSHclientDoc::OnFilePluginwizard()
// ---------- timers ----------

iCount = 0;
for (pos = m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
timerIt++)
{
CTimer * t;
m_TimerMap.GetNextAssoc (pos, strName, t);
if (t->bSelected)
if (timerIt->second->bSelected)
iCount++;
}

if (iCount)
{
ar.WriteString (NL "<!-- Timers -->" NL NL);
Save_Header_XML (ar, "timers", false);
for (pos = m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
timerIt++)
{
CTimer * t;
m_TimerMap.GetNextAssoc (pos, strName, t);
if (t->bSelected)
Save_One_Timer_XML (ar, t);
if (timerIt->second->bSelected)
Save_One_Timer_XML (ar, timerIt->second);
}
Save_Footer_XML (ar, "timers");
} // end of having some
Expand Down Expand Up @@ -1334,17 +1338,19 @@ void CMUSHclientDoc::OnFilePluginwizard()
// ---------- timers ----------

iCount = 0;
for (pos = m_TimerMap.GetStartPosition(); pos; )
for (CTimerMapIterator timerIt = m_TimerMap.begin ();
timerIt != m_TimerMap.end ();
)
{
CTimer * t;
m_TimerMap.GetNextAssoc (pos, strName, t);
CTimer * t = timerIt->second;
if (t->bSelected)
{
CTimerMapIterator it = timerIt++; // make copy before deleting
iCount++;
// delete its pointer
delete t;
// now delete its entry
m_TimerMap.RemoveKey (strName);
m_TimerMap.erase (it);
} // end of selected Timer

// show document modified
Expand Down
2 changes: 1 addition & 1 deletion scripting/methods/methods_info.cpp
Expand Up @@ -602,7 +602,7 @@ VARIANT CMUSHclientDoc::GetInfo(long InfoType)
case 217: SetUpVariantLong (vaResult, (long) m_nBytesOut); break;
case 218: SetUpVariantLong (vaResult, GetVariableMap ().GetCount ()); break;
case 219: SetUpVariantLong (vaResult, GetTriggerMap ().GetCount ()); break;
case 220: SetUpVariantLong (vaResult, GetTimerMap ().GetCount ()); break;
case 220: SetUpVariantLong (vaResult, GetTimerMap ().size ()); break;
case 221: SetUpVariantLong (vaResult, GetAliasMap ().GetCount ()); break;
case 222: SetUpVariantLong (vaResult, m_QueuedCommandsList.GetCount ()); break;
case 223: SetUpVariantLong (vaResult, m_strMapList.GetCount ()); break;
Expand Down
2 changes: 1 addition & 1 deletion scripting/methods/methods_plugins.cpp
Expand Up @@ -115,7 +115,7 @@ VARIANT CMUSHclientDoc::GetPluginInfo(LPCTSTR PluginID, short InfoType)
case 8: SetUpVariantString (vaResult, pPlugin->m_strPurpose); break;
case 9: SetUpVariantLong (vaResult, pPlugin->m_TriggerMap.GetCount ()); break;
case 10: SetUpVariantLong (vaResult, pPlugin->m_AliasMap.GetCount ()); break;
case 11: SetUpVariantLong (vaResult, pPlugin->m_TimerMap.GetCount ()); break;
case 11: SetUpVariantLong (vaResult, pPlugin->m_TimerMap.size ()); break;
case 12: SetUpVariantLong (vaResult, pPlugin->m_VariableMap.GetCount ()); break;
case 13:
if (pPlugin->m_tDateWritten.GetTime ()) // only if non-zero, otherwise return empty
Expand Down

0 comments on commit d5ff964

Please sign in to comment.