Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / change_tracker_base.cpp
blob966cb57ba4c92251883d13c2d98a73b8cfe0754e
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "stdpch.h"
20 #include "nel/misc/shared_memory.h"
21 #include "change_tracker_base.h"
25 * Create the mutex (either create or use existing)
27 bool CChangeTrackerBase::createMutex( sint32 mutid, bool createNew )
29 #ifdef USE_FAST_MUTEX
31 bool res = true;
32 if ( createNew )
33 trackerMutex().init();
35 #else
37 #ifdef NL_OS_WINDOWS
38 bool res = _TrackerMutex.createByName( NLMISC::toString( "%dM", mutid ).c_str() );
39 #else
40 bool res = _TrackerMutex.createByKey( mutid, createNew );
41 #endif
43 #endif
44 MIRROR_DEBUG( "MIRROR: TRACKER: Mutex %s (id %d) ", createNew?"created":"accessed", mutid );
45 _MutId = mutid;
46 return res;
51 * Record a change
53 void CChangeTrackerBase::recordChange( TDataSetIndex entityIndex )
55 // Note: could be shorter to link backwards but we need to link forward
56 // to read the changes in order (for partial sending)
57 #ifdef NL_DEBUG
58 nlassertex( (entityIndex != INVALID_DATASET_INDEX) && (entityIndex != LAST_CHANGED), ("E%d", entityIndex) );
59 #endif
61 // Protect consistency of two parallel calls to recordChange() for the same tracker
62 // and between recordChange() and popFirstChanged()
63 trackerMutex().enter();
65 // Test if the entity is already or not flagged as changed
66 if ( _Array[entityIndex].NextChanged==INVALID_DATASET_INDEX )
68 //nldebug( "Tracker (smid %u): adding change E%d", smid(), entityIndex );
69 // Set the entityIndex as changed, and last one
70 _Array[entityIndex].NextChanged = LAST_CHANGED;
72 if ( _Header->Last!=INVALID_DATASET_INDEX )
74 // Link the previous last one to the new last one
75 //nlassertex( _Header->Last != entityIndex, ( "Looping at %u", entityIndex ) );
76 _Array[_Header->Last].NextChanged = entityIndex;
77 //nldebug( "Tracker %p: E%d -> %d", _Array, _Header->Last, entityIndex );
79 else
81 // Set the first one if not set
82 _Header->First = entityIndex;
83 //nldebug( "Tracker %p: FIRST = %d", _Array, entityIndex );
84 //nldebug( "_Array = %p, _Array[%d].NextChanged = %d", _Array, entityIndex, _Array[entityIndex].NextChanged );
87 // Set the new last one
88 _Header->Last = entityIndex;
90 #ifdef COUNT_MIRROR_PROP_CHANGES
91 ++_Header->NbDistinctChanges;
92 #endif
94 //else
95 // nldebug( "Tracker %p: E%d already in list (%d)", _Array, entityIndex, _Array[entityIndex].NextChanged );
97 #ifdef COUNT_MIRROR_PROP_CHANGES
98 //++_Header->NbValuesSet; // should be atomic!
99 #endif
100 //nldebug( "Tracker (smid %u): E%d already in list (pointing to %d)", smid(), entityIndex, _Array[entityIndex].NextChanged );
101 trackerMutex().leave();
107 * Remove a change (slow) (assumes isAllocated())
109 void CChangeTrackerBase::cancelChange( TDataSetIndex entityIndex )
111 #ifdef NL_DEBUG
112 nlassertex( (entityIndex != INVALID_DATASET_INDEX) && (entityIndex != LAST_CHANGED), ("E%d", entityIndex) );
113 #endif
115 trackerMutex().enter();
117 // Find the change before the specified one, to make the link skip it
118 TDataSetIndex row = _Header->First;
119 if ( row != LAST_CHANGED )
121 if ( row == entityIndex )
123 // It was the first one
124 _Header->First = _Array[entityIndex].NextChanged;
125 _Array[entityIndex].NextChanged = INVALID_DATASET_INDEX;
126 if ( _Header->First == LAST_CHANGED ) // and it was the only one
127 _Header->Last = INVALID_DATASET_INDEX;
128 nldebug( "Cancelling change of E%u", entityIndex );
130 else
132 // It wasn't the first one
133 while ( (_Array[row].NextChanged != entityIndex) && (_Array[row].NextChanged != LAST_CHANGED) )
135 row = _Array[row].NextChanged;
137 if ( _Array[row].NextChanged == entityIndex )
139 _Array[row].NextChanged = _Array[entityIndex].NextChanged;
140 _Array[entityIndex].NextChanged = INVALID_DATASET_INDEX;
141 if ( _Header->Last == entityIndex ) // it was the last one
142 _Header->Last = row;
143 nldebug( "Cancelling change of E%u", entityIndex );
147 trackerMutex().leave();
152 * Return the number of changes (slow)
154 sint32 CChangeTrackerBase::nbChanges() const
156 sint32 nb = 0;
157 TDataSetRow entityIndex (getFirstChanged());
158 while ( entityIndex.getIndex() != LAST_CHANGED )
160 ++nb;
161 entityIndex = getNextChanged( entityIndex );
163 return nb;
168 * Display debug info (1 line)
170 void CChangeTrackerBase::displayTrackerInfo( const char *headerStr, const char *footerStrNotAllocd, NLMISC::CLog *log ) const
172 if ( isAllocated() )
173 log->displayNL( "%sAllocated, %d changes, smid %d mutid %d", headerStr, nbChanges(), smid(), mutid() );
174 else
175 log->displayNL( "%sNot allocated%s", headerStr, footerStrNotAllocd );