CBotClass::Lock() refactoring

dev-time-step
krzys-h 2015-12-31 16:11:19 +01:00
parent 2245863fcd
commit 48ab72d056
2 changed files with 39 additions and 66 deletions

View File

@ -27,6 +27,8 @@
#include "CBot/CBotInstr/CBotListArray.h" #include "CBot/CBotInstr/CBotListArray.h"
#include "CBot/CBotInstr/CBotEmpty.h" #include "CBot/CBotInstr/CBotEmpty.h"
#include "CBot/CBotVar/CBotVar.h"
#include "CBot/CBotExternalCall.h" #include "CBot/CBotExternalCall.h"
#include "CBot/CBotStack.h" #include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h" #include "CBot/CBotCStack.h"
@ -34,7 +36,7 @@
#include "CBot/CBotFileUtils.h" #include "CBot/CBotFileUtils.h"
#include "CBot/CBotCallMethode.h" #include "CBot/CBotCallMethode.h"
#include "CBot/CBotVar/CBotVar.h" #include <algorithm>
namespace CBot namespace CBot
{ {
@ -55,14 +57,10 @@ CBotClass::CBotClass(const std::string& name,
m_rMaj = nullptr; m_rMaj = nullptr;
m_IsDef = true; m_IsDef = true;
m_bIntrinsic= bIntrinsic; m_bIntrinsic= bIntrinsic;
m_cptLock = 0;
m_cptOne = 0;
m_nbVar = m_pParent == nullptr ? 0 : m_pParent->m_nbVar; m_nbVar = m_pParent == nullptr ? 0 : m_pParent->m_nbVar;
for ( int j= 0; j< 5 ; j++ ) m_lockCurrentCount = 0;
{ m_lockProg.clear();
m_ProgInLock[j] = nullptr;
}
// is located alone in the list // is located alone in the list
@ -126,38 +124,26 @@ void CBotClass::Purge()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CBotClass::Lock(CBotProgram* p) bool CBotClass::Lock(CBotProgram* prog)
{ {
int i = m_cptLock++; if (m_lockProg.size() == 0)
if ( i == 0 )
{ {
m_cptOne = 1; m_lockCurrentCount = 1;
m_ProgInLock[0] = p; m_lockProg.push_back(prog);
return true; return true;
} }
if ( p == m_ProgInLock[0] ) if (prog == m_lockProg[0])
{ {
m_cptOne++; m_lockCurrentCount++;
m_cptLock--; // has already been counted
return true; return true;
} }
for ( int j = 1 ; j <= i ; j++) if (std::find(m_lockProg.begin(), m_lockProg.end(), prog) != m_lockProg.end())
{ {
if ( p == m_ProgInLock[j] ) return false; // already pending
{
m_cptLock--;
return false; // already pending
}
} }
if ( i < 5 ) // max 5 in query m_lockProg.push_back(prog);
{
m_ProgInLock[i] = p; // located in a queue
}
else
m_cptLock--;
return false; return false;
} }
@ -165,38 +151,24 @@ bool CBotClass::Lock(CBotProgram* p)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CBotClass::Unlock() void CBotClass::Unlock()
{ {
if ( --m_cptOne > 0 ) return ; if (--m_lockCurrentCount > 0) return; // if called Lock() multiple times, wait for all to unlock
int i = --m_cptLock; m_lockProg.pop_front();
if ( i<0 )
{
m_cptLock = 0;
return;
}
for ( int j= 0; j< i ; j++ )
{
m_ProgInLock[j] = m_ProgInLock[j+1];
}
m_ProgInLock[i] = nullptr;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CBotClass::FreeLock(CBotProgram* p) void CBotClass::FreeLock(CBotProgram* prog)
{ {
CBotClass* pClass = m_ExClass; CBotClass* pClass = m_ExClass;
while ( pClass != nullptr ) while (pClass != nullptr)
{ {
if ( p == pClass->m_ProgInLock[0] ) if (pClass->m_lockProg.size() > 0 && prog == pClass->m_lockProg[0])
{ {
pClass->m_cptLock -= pClass->m_cptOne; pClass->m_lockCurrentCount = 0;
pClass->m_cptOne = 0;
} }
for ( int j = 1; j < 5 ; j++ ) pClass->m_lockProg.erase(std::remove(pClass->m_lockProg.begin(), pClass->m_lockProg.end(), prog));
if ( p == pClass->m_ProgInLock[j] )
pClass->m_cptLock--;
pClass = pClass->m_ExNext; pClass = pClass->m_ExNext;
} }

View File

@ -24,6 +24,7 @@
#include "CBot/CBotVar/CBotVar.h" #include "CBot/CBotVar/CBotVar.h"
#include <string> #include <string>
#include <deque>
namespace CBot namespace CBot
{ {
@ -333,23 +334,24 @@ public:
*/ */
static bool RestoreStaticState(FILE* pf); static bool RestoreStaticState(FILE* pf);
/*! /**
* \brief Lock * \brief Request a lock on this class (for "synchronized" keyword)
* \param p * \param prog Program that requests the lock
* \return * \return true if lock was acquired, false if the lock is already taken
*/ */
bool Lock(CBotProgram* p); bool Lock(CBotProgram* prog);
/*! /**
* \brief Unlock * \brief Release the lock acquired in Lock()
* If you call Lock() multiple times for the same program, you have to call Unlock() multiple times too
*/ */
void Unlock(); void Unlock();
/*! /**
* \brief FreeLock * \brief Release all locks in all classes held by this program
* \param p * \param prog Program to release the locks from
*/ */
static void FreeLock(CBotProgram* p); static void FreeLock(CBotProgram* prog);
/*! /*!
* \brief CheckCall Test if a procedure name is already defined somewhere. * \brief CheckCall Test if a procedure name is already defined somewhere.
@ -383,12 +385,11 @@ private:
CBotFunction* m_pMethod; CBotFunction* m_pMethod;
void (*m_rMaj) ( CBotVar* pThis, void* pUser ); void (*m_rMaj) ( CBotVar* pThis, void* pUser );
friend class CBotVarClass; friend class CBotVarClass;
//! For Lock / UnLock.
int m_cptLock; //! How many times the program currently holding the lock called Lock()
//! Lock for reentrancy. int m_lockCurrentCount;
int m_cptOne; //! Programs waiting for lock
//! Processes waiting for sync. std::deque<CBotProgram*> m_lockProg;
CBotProgram* m_ProgInLock[5];
}; };
} // namespace CBot } // namespace CBot