diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 7ebcefa..822b74a 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/GeomDB.cpp b/GeomDB.cpp index 26f79fe..101749f 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -30,9 +30,31 @@ #include "/EgtDev/Include/SELkKeyProc.h" #include #include +#include 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 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 pụ 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() ; } diff --git a/GeomDB.h b/GeomDB.h index 5295b92..dd83216 100644 --- a/GeomDB.h +++ b/GeomDB.h @@ -20,6 +20,7 @@ #include "SelManager.h" #include "GdbMaterialMgr.h" #include "/EgtDev/Include/EGkGeomDB.h" +#include //---------------------------------------------------------------------------- class GeomDB : public IGeomDB @@ -229,7 +230,7 @@ class GeomDB : public IGeomDB { return dynamic_cast( GetGdbObj( nId)) ; } const GdbGroup* GetGdbGroup( int nId) const { return dynamic_cast( GetGdbObj( nId)) ; } - bool InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTestId = true) ; + bool InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLockAddErase = true, bool bTestId = true) ; int Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGlob) ; bool Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob) ; bool Erase( GdbObj* pGObj) ; @@ -253,10 +254,11 @@ class GeomDB : public IGeomDB { return m_IterManager.RemoveGdbIterator( pIter) ; } private : - IdManager m_IdManager ; // gestore del nuovo Id - IterManager m_IterManager ; // gestore lista iteratori attivi - SelManager m_SelManager ; // gestore lista oggetti selezionati - GdbMaterialMgr m_MatManager ; // gestore lista materiali - GdbGroup m_GrpRadix ; // gruppo radice di tutto il DB - Frame3d m_GridFrame ; // riferimento della griglia + IdManager m_IdManager ; // gestore del nuovo Id + IterManager m_IterManager ; // gestore lista iteratori attivi + SelManager m_SelManager ; // gestore lista oggetti selezionati + GdbMaterialMgr m_MatManager ; // gestore lista materiali + GdbGroup m_GrpRadix ; // gruppo radice di tutto il DB + Frame3d m_GridFrame ; // riferimento della griglia + std::atomic_flag m_bAddEraseOn ; // flag esecuzione inserimento o cancellazione in corso (per multi thread) } ;