diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llmath/llvolumemgr.cpp | 182 |
1 files changed, 141 insertions, 41 deletions
diff --git a/linden/indra/llmath/llvolumemgr.cpp b/linden/indra/llmath/llvolumemgr.cpp index db99959..d9bca70 100644 --- a/linden/indra/llmath/llvolumemgr.cpp +++ b/linden/indra/llmath/llvolumemgr.cpp | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | //#define DEBUG_VOLUME | 37 | //#define DEBUG_VOLUME |
38 | 38 | ||
39 | LLVolumeMgr* gVolumeMgr = 0; | 39 | //LLVolumeMgr* gVolumeMgr = 0; |
40 | 40 | ||
41 | const F32 BASE_THRESHOLD = 0.03f; | 41 | const F32 BASE_THRESHOLD = 0.03f; |
42 | 42 | ||
@@ -49,37 +49,23 @@ F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD, | |||
49 | //static | 49 | //static |
50 | F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; | 50 | F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; |
51 | 51 | ||
52 | //============================================================================ | ||
53 | //static | ||
54 | void LLVolumeMgr::initClass() | ||
55 | { | ||
56 | gVolumeMgr = new LLVolumeMgr(); | ||
57 | } | ||
58 | |||
59 | //static | ||
60 | BOOL LLVolumeMgr::cleanupClass() | ||
61 | { | ||
62 | BOOL res = FALSE; | ||
63 | if (gVolumeMgr) { | ||
64 | res = gVolumeMgr->cleanup(); | ||
65 | delete gVolumeMgr; | ||
66 | gVolumeMgr = 0; | ||
67 | } | ||
68 | return res; | ||
69 | } | ||
70 | 52 | ||
71 | //============================================================================ | 53 | //============================================================================ |
72 | 54 | ||
73 | LLVolumeMgr::LLVolumeMgr() | 55 | LLVolumeMgr::LLVolumeMgr() |
56 | : mDataMutex(NULL) | ||
74 | { | 57 | { |
75 | mDataMutex = new LLMutex(gAPRPoolp); | 58 | // the LLMutex magic interferes with easy unit testing, |
76 | // mNumVolumes = 0; | 59 | // so you now must manually call useMutex() to use it |
60 | //mDataMutex = new LLMutex(gAPRPoolp); | ||
77 | } | 61 | } |
78 | 62 | ||
79 | LLVolumeMgr::~LLVolumeMgr() | 63 | LLVolumeMgr::~LLVolumeMgr() |
80 | { | 64 | { |
81 | cleanup(); | 65 | cleanup(); |
66 | |||
82 | delete mDataMutex; | 67 | delete mDataMutex; |
68 | mDataMutex = NULL; | ||
83 | } | 69 | } |
84 | 70 | ||
85 | BOOL LLVolumeMgr::cleanup() | 71 | BOOL LLVolumeMgr::cleanup() |
@@ -90,7 +76,10 @@ BOOL LLVolumeMgr::cleanup() | |||
90 | } | 76 | } |
91 | #endif | 77 | #endif |
92 | BOOL no_refs = TRUE; | 78 | BOOL no_refs = TRUE; |
93 | mDataMutex->lock(); | 79 | if (mDataMutex) |
80 | { | ||
81 | mDataMutex->lock(); | ||
82 | } | ||
94 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), | 83 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), |
95 | end = mVolumeLODGroups.end(); | 84 | end = mVolumeLODGroups.end(); |
96 | iter != end; iter++) | 85 | iter != end; iter++) |
@@ -106,29 +95,37 @@ BOOL LLVolumeMgr::cleanup() | |||
106 | volgroupp->unref();// this ); | 95 | volgroupp->unref();// this ); |
107 | } | 96 | } |
108 | mVolumeLODGroups.clear(); | 97 | mVolumeLODGroups.clear(); |
109 | mDataMutex->unlock(); | 98 | if (mDataMutex) |
99 | { | ||
100 | mDataMutex->unlock(); | ||
101 | } | ||
110 | return no_refs; | 102 | return no_refs; |
111 | } | 103 | } |
112 | 104 | ||
105 | // whatever calls getVolume() never owns the LLVolume* and | ||
106 | // cannot keep references for long since it may be deleted | ||
107 | // later. For best results hold it in an LLPointer<LLVolume>. | ||
113 | LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail) | 108 | LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail) |
114 | { | 109 | { |
115 | LLVolumeLODGroup* volgroupp; | 110 | LLVolumeLODGroup* volgroupp; |
116 | mDataMutex->lock(); | 111 | if (mDataMutex) |
112 | { | ||
113 | mDataMutex->lock(); | ||
114 | } | ||
117 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params); | 115 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params); |
118 | if( iter == mVolumeLODGroups.end() ) | 116 | if( iter == mVolumeLODGroups.end() ) |
119 | { | 117 | { |
120 | volgroupp = new LLVolumeLODGroup(volume_params); | 118 | volgroupp = createNewGroup(volume_params); |
121 | const LLVolumeParams* params = &(volgroupp->getParams()); | ||
122 | mVolumeLODGroups[params] = volgroupp; | ||
123 | volgroupp->ref(); // initial reference | ||
124 | } | 119 | } |
125 | else | 120 | else |
126 | { | 121 | { |
127 | volgroupp = iter->second; | 122 | volgroupp = iter->second; |
128 | } | 123 | } |
129 | volgroupp->ref();// this ); | 124 | volgroupp->ref(); |
130 | mDataMutex->unlock(); | 125 | if (mDataMutex) |
131 | // mNumVolumes++; | 126 | { |
127 | mDataMutex->unlock(); | ||
128 | } | ||
132 | #ifdef DEBUG_VOLUME | 129 | #ifdef DEBUG_VOLUME |
133 | { | 130 | { |
134 | lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl; | 131 | lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl; |
@@ -137,6 +134,27 @@ LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 | |||
137 | return volgroupp->getLOD(detail); | 134 | return volgroupp->getLOD(detail); |
138 | } | 135 | } |
139 | 136 | ||
137 | // virtual | ||
138 | LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const | ||
139 | { | ||
140 | LLVolumeLODGroup* volgroupp = NULL; | ||
141 | if (mDataMutex) | ||
142 | { | ||
143 | mDataMutex->lock(); | ||
144 | } | ||
145 | volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params); | ||
146 | if( iter != mVolumeLODGroups.end() ) | ||
147 | { | ||
148 | volgroupp = iter->second; | ||
149 | } | ||
150 | if (mDataMutex) | ||
151 | { | ||
152 | mDataMutex->unlock(); | ||
153 | } | ||
154 | return volgroupp; | ||
155 | } | ||
156 | |||
157 | // virtual | ||
140 | void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | 158 | void LLVolumeMgr::cleanupVolume(LLVolume *volumep) |
141 | { | 159 | { |
142 | if (volumep->isUnique()) | 160 | if (volumep->isUnique()) |
@@ -145,12 +163,18 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | |||
145 | return; | 163 | return; |
146 | } | 164 | } |
147 | LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams()); | 165 | LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams()); |
148 | mDataMutex->lock(); | 166 | if (mDataMutex) |
167 | { | ||
168 | mDataMutex->lock(); | ||
169 | } | ||
149 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); | 170 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); |
150 | if( iter == mVolumeLODGroups.end() ) | 171 | if( iter == mVolumeLODGroups.end() ) |
151 | { | 172 | { |
152 | llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl; | 173 | llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl; |
153 | mDataMutex->unlock(); | 174 | if (mDataMutex) |
175 | { | ||
176 | mDataMutex->unlock(); | ||
177 | } | ||
154 | return; | 178 | return; |
155 | } | 179 | } |
156 | else | 180 | else |
@@ -164,9 +188,11 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | |||
164 | mVolumeLODGroups.erase(params); | 188 | mVolumeLODGroups.erase(params); |
165 | volgroupp->unref();// this ); | 189 | volgroupp->unref();// this ); |
166 | } | 190 | } |
167 | // mNumVolumes--; | ||
168 | } | 191 | } |
169 | mDataMutex->unlock(); | 192 | if (mDataMutex) |
193 | { | ||
194 | mDataMutex->unlock(); | ||
195 | } | ||
170 | 196 | ||
171 | #ifdef DEBUG_VOLUME | 197 | #ifdef DEBUG_VOLUME |
172 | { | 198 | { |
@@ -175,10 +201,43 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | |||
175 | #endif | 201 | #endif |
176 | } | 202 | } |
177 | 203 | ||
204 | #ifdef DEBUG_VOLUME | ||
205 | S32 LLVolumeMgr::getTotalRefCount() const | ||
206 | { | ||
207 | S32 total_ref_count = 0; | ||
208 | for ( volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.begin(), | ||
209 | end = mVolumeLODGroups.end(); | ||
210 | iter != end; iter++) | ||
211 | { | ||
212 | total_ref_count += iter->second->getTotalVolumeRefCount(); | ||
213 | } | ||
214 | return total_ref_count; | ||
215 | } | ||
216 | |||
217 | S32 LLVolumeMgr::getGroupCount() const | ||
218 | { | ||
219 | return mVolumeLODGroups.size(); | ||
220 | } | ||
221 | #endif | ||
222 | |||
223 | // protected | ||
224 | LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params) | ||
225 | { | ||
226 | LLVolumeLODGroup* group = new LLVolumeLODGroup(volume_params); | ||
227 | const LLVolumeParams* params = &(group->getParams()); | ||
228 | mVolumeLODGroups[params] = group; | ||
229 | group->ref(); // initial reference | ||
230 | return group; | ||
231 | } | ||
232 | |||
233 | // virtual | ||
178 | void LLVolumeMgr::dump() | 234 | void LLVolumeMgr::dump() |
179 | { | 235 | { |
180 | F32 avg = 0.f; | 236 | F32 avg = 0.f; |
181 | mDataMutex->lock(); | 237 | if (mDataMutex) |
238 | { | ||
239 | mDataMutex->lock(); | ||
240 | } | ||
182 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), | 241 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), |
183 | end = mVolumeLODGroups.end(); | 242 | end = mVolumeLODGroups.end(); |
184 | iter != end; iter++) | 243 | iter != end; iter++) |
@@ -188,16 +247,30 @@ void LLVolumeMgr::dump() | |||
188 | } | 247 | } |
189 | int count = (int)mVolumeLODGroups.size(); | 248 | int count = (int)mVolumeLODGroups.size(); |
190 | avg = count ? avg / (F32)count : 0.0f; | 249 | avg = count ? avg / (F32)count : 0.0f; |
191 | mDataMutex->unlock(); | 250 | if (mDataMutex) |
251 | { | ||
252 | mDataMutex->unlock(); | ||
253 | } | ||
192 | llinfos << "Average usage of LODs " << avg << llendl; | 254 | llinfos << "Average usage of LODs " << avg << llendl; |
193 | } | 255 | } |
194 | 256 | ||
257 | void LLVolumeMgr::useMutex() | ||
258 | { | ||
259 | if (!mDataMutex) | ||
260 | { | ||
261 | mDataMutex = new LLMutex(gAPRPoolp); | ||
262 | } | ||
263 | } | ||
264 | |||
195 | std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) | 265 | std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) |
196 | { | 266 | { |
197 | s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", "; | 267 | s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", "; |
198 | 268 | ||
199 | S32 total_refs = 0; | 269 | S32 total_refs = 0; |
200 | volume_mgr.mDataMutex->lock(); | 270 | if (volume_mgr.mDataMutex) |
271 | { | ||
272 | volume_mgr.mDataMutex->lock(); | ||
273 | } | ||
201 | 274 | ||
202 | LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin(); | 275 | LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin(); |
203 | LLVolumeMgr::volume_lod_group_map_iter end = volume_mgr.mVolumeLODGroups.end(); | 276 | LLVolumeMgr::volume_lod_group_map_iter end = volume_mgr.mVolumeLODGroups.end(); |
@@ -208,7 +281,10 @@ std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) | |||
208 | s << ", " << (*volgroupp); | 281 | s << ", " << (*volgroupp); |
209 | } | 282 | } |
210 | 283 | ||
211 | volume_mgr.mDataMutex->unlock(); | 284 | if (volume_mgr.mDataMutex) |
285 | { | ||
286 | volume_mgr.mDataMutex->unlock(); | ||
287 | } | ||
212 | 288 | ||
213 | s << ", total_refs=" << total_refs << " }"; | 289 | s << ", total_refs=" << total_refs << " }"; |
214 | return s; | 290 | return s; |
@@ -222,15 +298,39 @@ LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams ¶ms) | |||
222 | for (i = 0; i < NUM_LODS; i++) | 298 | for (i = 0; i < NUM_LODS; i++) |
223 | { | 299 | { |
224 | mLODRefs[i] = 0; | 300 | mLODRefs[i] = 0; |
225 | mVolumeLODs[i] = NULL; | 301 | // no need to initialize mVolumeLODs, they are smart pointers |
302 | //mVolumeLODs[i] = NULL; | ||
226 | mAccessCount[i] = 0; | 303 | mAccessCount[i] = 0; |
227 | } | 304 | } |
228 | } | 305 | } |
229 | 306 | ||
307 | #ifdef DEBUG_VOLUME | ||
308 | S32 LLVolumeLODGroup::getTotalVolumeRefCount() const | ||
309 | { | ||
310 | S32 total_ref_count = 0; | ||
311 | for (S32 i = 0; i < NUM_LODS; i++) | ||
312 | { | ||
313 | total_ref_count += mLODRefs[i]; | ||
314 | } | ||
315 | return total_ref_count; | ||
316 | } | ||
317 | #endif | ||
318 | |||
319 | // protected | ||
230 | LLVolumeLODGroup::~LLVolumeLODGroup() | 320 | LLVolumeLODGroup::~LLVolumeLODGroup() |
231 | { | 321 | { |
322 | destroy(); | ||
232 | } | 323 | } |
233 | 324 | ||
325 | // protected | ||
326 | void LLVolumeLODGroup::destroy() | ||
327 | { | ||
328 | for (S32 i = 0; i < NUM_LODS; i++) | ||
329 | { | ||
330 | // remember that mVolumeLODs are smart pointers! | ||
331 | mVolumeLODs[i] = NULL; | ||
332 | } | ||
333 | } | ||
234 | 334 | ||
235 | LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) | 335 | LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) |
236 | { | 336 | { |
@@ -242,7 +342,7 @@ LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) | |||
242 | mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]); | 342 | mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]); |
243 | } | 343 | } |
244 | mLODRefs[detail]++; | 344 | mLODRefs[detail]++; |
245 | return mVolumeLODs[detail]; | 345 | return mVolumeLODs[detail].get(); |
246 | } | 346 | } |
247 | 347 | ||
248 | BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) | 348 | BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) |