aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llvolumemgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llmath/llvolumemgr.cpp182
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
39LLVolumeMgr* gVolumeMgr = 0; 39//LLVolumeMgr* gVolumeMgr = 0;
40 40
41const F32 BASE_THRESHOLD = 0.03f; 41const F32 BASE_THRESHOLD = 0.03f;
42 42
@@ -49,37 +49,23 @@ F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
49//static 49//static
50F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; 50F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
51 51
52//============================================================================
53//static
54void LLVolumeMgr::initClass()
55{
56 gVolumeMgr = new LLVolumeMgr();
57}
58
59//static
60BOOL 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
73LLVolumeMgr::LLVolumeMgr() 55LLVolumeMgr::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
79LLVolumeMgr::~LLVolumeMgr() 63LLVolumeMgr::~LLVolumeMgr()
80{ 64{
81 cleanup(); 65 cleanup();
66
82 delete mDataMutex; 67 delete mDataMutex;
68 mDataMutex = NULL;
83} 69}
84 70
85BOOL LLVolumeMgr::cleanup() 71BOOL 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>.
113LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail) 108LLVolume *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
138LLVolumeLODGroup* 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
140void LLVolumeMgr::cleanupVolume(LLVolume *volumep) 158void 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
205S32 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
217S32 LLVolumeMgr::getGroupCount() const
218{
219 return mVolumeLODGroups.size();
220}
221#endif
222
223// protected
224LLVolumeLODGroup* 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
178void LLVolumeMgr::dump() 234void 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
257void LLVolumeMgr::useMutex()
258{
259 if (!mDataMutex)
260 {
261 mDataMutex = new LLMutex(gAPRPoolp);
262 }
263}
264
195std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) 265std::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 &params)
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
308S32 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
230LLVolumeLODGroup::~LLVolumeLODGroup() 320LLVolumeLODGroup::~LLVolumeLODGroup()
231{ 321{
322 destroy();
232} 323}
233 324
325// protected
326void 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
235LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) 335LLVolume * 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
248BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) 348BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)