EgtGeomKernel 2.5f5 :

- aggiunta gestione lock tra thread diversi delle operazioni di lettura, scrittura, copia e relocate nel DB geometrico tramite classe LockAddErase che usa std::atomic_flag.
This commit is contained in:
DarioS
2023-06-23 09:15:10 +02:00
parent 8a3d46416d
commit 8f84f78b16
3 changed files with 79 additions and 16 deletions
+70 -9
View File
@@ -30,9 +30,31 @@
#include "/EgtDev/Include/SELkKeyProc.h"
#include <new>
#include <stack>
#include <thread>
using namespace std ;
//----------------------------------------------------------------------------
class LockAddErase
{
public :
LockAddErase(std::atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse)
{ if ( ! m_bUse) return ;
while ( m_bAddEraseOn.test_and_set()) {
this_thread::sleep_for( chrono::nanoseconds{ 1}) ;
}
} ;
~LockAddErase( void)
{ if ( ! m_bUse) return ;
m_bAddEraseOn.clear() ;
} ;
private :
std::atomic_flag& m_bAddEraseOn ;
bool m_bUse ;
} ;
//----------------------------------------------------------------------------
IGeomDB*
CreateGeomDB( void)
@@ -68,6 +90,7 @@ CreateGeomDB( void)
//----------------------------------------------------------------------------
GeomDB::GeomDB( void)
{
m_bAddEraseOn.clear() ;
m_GrpRadix.SetGeomDB( this) ;
m_GrpRadix.m_nId = GDB_ID_ROOT ;
m_GrpRadix.SetMaterial( Color()) ;
@@ -595,25 +618,32 @@ GeomDB::GetGdbObj( int nId) const
//----------------------------------------------------------------------------
bool
GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTestId)
GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLockAddErase, bool bTestId)
{
// verifico validità oggetto puntato
if ( pGObj == nullptr)
return false ;
// se richiesta, verifica validità e unicità del nome
if ( bTestId && ( pGObj->m_nId <= GDB_ID_ROOT || ExistsObj( pGObj->m_nId)))
// verifico validità del riferimento
if ( nRefId < GDB_ID_ROOT)
return false ;
// oggetto e riferimento non possono essere la stessa cosa
if ( pGObj->m_nId == nRefId)
return ( ! IS_GDB_SON( nSonBeforeAfter)) ;
// verifico unicità esecuzione, se necessaria
LockAddErase Lock( m_bAddEraseOn, bLockAddErase) ;
// cerco il riferimento
GdbObj* pGRef = GetGdbObj( nRefId) ;
if ( pGRef == nullptr)
return false ;
// se richiesta, verifica validità e unicità del nome
if ( bTestId && ( pGObj->m_nId <= GDB_ID_ROOT || ExistsObj( pGObj->m_nId)))
return false ;
// assegno il riferimento al DB geometrico
pGObj->SetGeomDB( this) ;
@@ -667,6 +697,8 @@ GeomDB::InsertGroup( int nId, int nRefId, int nSonBeforeAfter, const Frame3d& fr
// verifico validità apparente RefId
if ( nRefId < GDB_ID_ROOT)
return GDB_ID_NULL ;
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// verifico validità Id
if ( nId <= GDB_ID_ROOT)
nId = m_IdManager.GetNewId() ;
@@ -681,7 +713,7 @@ GeomDB::InsertGroup( int nId, int nRefId, int nSonBeforeAfter, const Frame3d& fr
// assegno riferimento
pGdbGroup->SetFrame( frFrame) ;
// inserisco nel DB
if ( ! InsertInGeomDB( pGdbGroup, nRefId, nSonBeforeAfter)) {
if ( ! InsertInGeomDB( pGdbGroup, nRefId, nSonBeforeAfter, false)) {
delete pGdbGroup ;
return GDB_ID_NULL ;
}
@@ -702,6 +734,8 @@ GeomDB::InsertGeoObj( int nId, int nRefId, int nSonBeforeAfter, IGeoObj* pGeoObj
{
// assegno GeoObj a gestore puntatore con rilascio automatico
PtrOwner<IGeoObj> pRPGeoObj( pGeoObj) ;
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// verifico validità identificativo
if ( nId <= GDB_ID_ROOT)
nId = m_IdManager.GetNewId() ;
@@ -719,7 +753,7 @@ GeomDB::InsertGeoObj( int nId, int nRefId, int nSonBeforeAfter, IGeoObj* pGeoObj
// assegno dati
pGdbGeo->m_pGeoObj = Release( pRPGeoObj) ;
// inserisco nel DB
if ( ! InsertInGeomDB( pGdbGeo, nRefId, nSonBeforeAfter)) {
if ( ! InsertInGeomDB( pGdbGeo, nRefId, nSonBeforeAfter, false)) {
delete pGdbGeo ;
return GDB_ID_NULL ;
}
@@ -1202,6 +1236,9 @@ GeomDB::GetRefBBox( int nId, const Frame3d& frRef, BBox3d& b3Ref, int nFlag) con
int
GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGlob)
{
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// verifico Id destinazione
if ( nIdDest <= GDB_ID_ROOT)
nIdDest = m_IdManager.GetNewId() ;
@@ -1244,7 +1281,7 @@ GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGl
}
// inserisco nel DB (non rilascio il puntatore)
if ( ! InsertInGeomDB( pGdODest, nRefId, nSonBeforeAfter))
if ( ! InsertInGeomDB( pGdODest, nRefId, nSonBeforeAfter, false))
return GDB_ID_NULL ;
// rilascio il puntatore
@@ -1256,10 +1293,17 @@ GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGl
bool
GeomDB::Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob)
{
// l'oggetto e il riferimento non possono coincidere
// verifico validità del riferimento
if ( nRefId < GDB_ID_ROOT)
return false ;
// l'oggetto e il riferimento non possono coincidere
if ( nId == nRefId)
return ( ! IS_GDB_SON( nSonBeforeAfter)) ;
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// verifico esistenza dell'oggetto
GdbObj* pGdbObj = GetGdbObj( nId) ;
if ( pGdbObj == nullptr)
@@ -1303,7 +1347,7 @@ GeomDB::Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob)
pGdbObj->Remove() ;
// lo inserisco nella posizione opportuna
if ( ! InsertInGeomDB( pGdbObj, nRefId, nSonBeforeAfter, false)) {
if ( ! InsertInGeomDB( pGdbObj, nRefId, nSonBeforeAfter, false, false)) {
// in caso di errore (condizione assai remota qui) cancello tutto
m_IdManager.RemoveObj( pGdbObj->m_nId) ;
m_SelManager.RemoveObj( pGdbObj) ;
@@ -1384,9 +1428,14 @@ GeomDB::GetNewId( void) const
bool
GeomDB::ChangeId( int nId, int nNewId)
{
// se Id non validi, ritorno errore
if ( nId <= GDB_ID_ROOT || nNewId <= GDB_ID_ROOT)
return false ;
// se Id identici, non faccio alcunché
if ( nNewId == nId)
return true ;
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// verifico nuovo Id
if ( ExistsObj( nNewId))
return false ;
@@ -1427,7 +1476,10 @@ GeomDB::Erase( GdbObj* pGdbObj)
if ( pGdbObj == nullptr || pGdbObj == &m_GrpRadix)
return false ;
// notifico eventuale UserObj
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// notifico eventuale UserObj
if ( pGdbObj->m_pUserObj != nullptr) {
// recupero il successivo
const GdbObj* pGdbNext = pGdbObj->GetNext() ;
@@ -1452,6 +1504,10 @@ GeomDB::RemoveGeoObjAndErase( int nId)
// non si può cancellare il gruppo radice (escludo anche Id non validi)
if ( nId <= GDB_ID_ROOT)
return nullptr ;
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// recupero l'oggetto geometrico
GdbGeo* pGdbGeo = ::GetGdbGeo( m_IdManager.FindObj( nId)) ;
if ( pGdbGeo == nullptr)
@@ -1459,6 +1515,7 @@ GeomDB::RemoveGeoObjAndErase( int nId)
IGeoObj* pGeoObj = pGdbGeo->m_pGeoObj ;
// annullo il riferimento alla geometria nell'entità
pGdbGeo->m_pGeoObj = nullptr ;
// tolgo dalla lista e disalloco
pGdbGeo->Remove() ;
delete pGdbGeo ;
@@ -1494,6 +1551,10 @@ GeomDB::EmptyGroup( GdbObj* pGdbObj)
GdbGroup* pGrp = ::GetGdbGroup( pGdbObj) ;
if ( pGrp == nullptr)
return false ;
// verifico unicità esecuzione
LockAddErase Lock( m_bAddEraseOn) ;
// lo svuoto
return pGrp->Clear() ;
}