[5] | 1 | /* |
---|
| 2 | ----------------------------------------------------------------------------- |
---|
| 3 | This source file is part of OGRE |
---|
| 4 | (Object-oriented Graphics Rendering Engine) |
---|
| 5 | For the latest info, see http://www.ogre3d.org/ |
---|
| 6 | |
---|
| 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd |
---|
| 8 | Also see acknowledgements in Readme.html |
---|
| 9 | |
---|
| 10 | This program is free software; you can redistribute it and/or modify it under |
---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software |
---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later |
---|
| 13 | version. |
---|
| 14 | |
---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT |
---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
---|
| 18 | |
---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with |
---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
---|
| 22 | http://www.gnu.org/copyleft/lesser.txt. |
---|
| 23 | |
---|
| 24 | You may alternatively use this source under the terms of a specific version of |
---|
| 25 | the OGRE Unrestricted License provided you have obtained such a license from |
---|
| 26 | Torus Knot Software Ltd. |
---|
| 27 | ----------------------------------------------------------------------------- |
---|
| 28 | */ |
---|
| 29 | #include "OgreStableHeaders.h" |
---|
| 30 | #include "OgreResourceBackgroundQueue.h" |
---|
| 31 | #include "OgreLogManager.h" |
---|
| 32 | #include "OgreException.h" |
---|
| 33 | #include "OgreResourceGroupManager.h" |
---|
| 34 | #include "OgreResourceManager.h" |
---|
| 35 | #include "OgreRoot.h" |
---|
| 36 | #include "OgreRenderSystem.h" |
---|
| 37 | |
---|
| 38 | namespace Ogre { |
---|
| 39 | |
---|
| 40 | //------------------------------------------------------------------------ |
---|
| 41 | //----------------------------------------------------------------------- |
---|
| 42 | template<> ResourceBackgroundQueue* Singleton<ResourceBackgroundQueue>::ms_Singleton = 0; |
---|
| 43 | ResourceBackgroundQueue* ResourceBackgroundQueue::getSingletonPtr(void) |
---|
| 44 | { |
---|
| 45 | return ms_Singleton; |
---|
| 46 | } |
---|
| 47 | ResourceBackgroundQueue& ResourceBackgroundQueue::getSingleton(void) |
---|
| 48 | { |
---|
| 49 | assert( ms_Singleton ); return ( *ms_Singleton ); |
---|
| 50 | } |
---|
| 51 | //----------------------------------------------------------------------- |
---|
| 52 | //------------------------------------------------------------------------ |
---|
| 53 | ResourceBackgroundQueue::ResourceBackgroundQueue() |
---|
| 54 | :mNextTicketID(0), mStartThread(true), mThread(0) |
---|
| 55 | #if OGRE_THREAD_SUPPORT |
---|
| 56 | , mShuttingDown(false) |
---|
| 57 | #endif |
---|
| 58 | { |
---|
| 59 | } |
---|
| 60 | //------------------------------------------------------------------------ |
---|
| 61 | ResourceBackgroundQueue::~ResourceBackgroundQueue() |
---|
| 62 | { |
---|
| 63 | shutdown(); |
---|
| 64 | } |
---|
| 65 | //------------------------------------------------------------------------ |
---|
| 66 | void ResourceBackgroundQueue::initialise(void) |
---|
| 67 | { |
---|
| 68 | #if OGRE_THREAD_SUPPORT |
---|
| 69 | if (mStartThread) |
---|
| 70 | { |
---|
| 71 | { |
---|
| 72 | OGRE_LOCK_AUTO_MUTEX |
---|
| 73 | mShuttingDown = false; |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | RenderSystem* rs = Root::getSingleton().getRenderSystem(); |
---|
| 77 | |
---|
| 78 | LogManager::getSingleton().logMessage( |
---|
| 79 | "ResourceBackgroundQueue - threading enabled, starting own thread"); |
---|
| 80 | { |
---|
| 81 | OGRE_LOCK_MUTEX_NAMED(initMutex, initLock) |
---|
| 82 | |
---|
| 83 | // Call thread creation pre-hook |
---|
| 84 | rs->preExtraThreadsStarted(); |
---|
| 85 | |
---|
| 86 | mThread = new boost::thread( |
---|
| 87 | boost::function0<void>(&ResourceBackgroundQueue::threadFunc)); |
---|
| 88 | // Wait for init to finish before allowing main thread to continue |
---|
| 89 | // this releases the initMutex until notified |
---|
| 90 | OGRE_THREAD_WAIT(initSync, initLock) |
---|
| 91 | |
---|
| 92 | // Call thread creation post-hook |
---|
| 93 | rs->postExtraThreadsStarted(); |
---|
| 94 | } |
---|
| 95 | |
---|
| 96 | } |
---|
| 97 | else |
---|
| 98 | { |
---|
| 99 | LogManager::getSingleton().logMessage( |
---|
| 100 | "ResourceBackgroundQueue - threading enabled, user thread"); |
---|
| 101 | } |
---|
| 102 | #else |
---|
| 103 | LogManager::getSingleton().logMessage( |
---|
| 104 | "ResourceBackgroundQueue - threading disabled"); |
---|
| 105 | #endif |
---|
| 106 | } |
---|
| 107 | //------------------------------------------------------------------------ |
---|
| 108 | void ResourceBackgroundQueue::shutdown(void) |
---|
| 109 | { |
---|
| 110 | #if OGRE_THREAD_SUPPORT |
---|
| 111 | if (mThread) |
---|
| 112 | { |
---|
| 113 | // Put a shutdown request on the queue |
---|
| 114 | Request req; |
---|
| 115 | req.type = RT_SHUTDOWN; |
---|
| 116 | addRequest(req); |
---|
| 117 | // Wait for thread to finish |
---|
| 118 | mThread->join(); |
---|
| 119 | delete mThread; |
---|
| 120 | mThread = 0; |
---|
| 121 | mRequestQueue.clear(); |
---|
| 122 | mRequestTicketMap.clear(); |
---|
| 123 | } |
---|
| 124 | #endif |
---|
| 125 | } |
---|
| 126 | //------------------------------------------------------------------------ |
---|
| 127 | BackgroundProcessTicket ResourceBackgroundQueue::initialiseResourceGroup( |
---|
| 128 | const String& name, ResourceBackgroundQueue::Listener* listener) |
---|
| 129 | { |
---|
| 130 | #if OGRE_THREAD_SUPPORT |
---|
| 131 | if (!mThread && mStartThread) |
---|
| 132 | { |
---|
| 133 | OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, |
---|
| 134 | "Thread not initialised", |
---|
| 135 | "ResourceBackgroundQueue::initialiseResourceGroup"); |
---|
| 136 | } |
---|
| 137 | // queue a request |
---|
| 138 | Request req; |
---|
| 139 | req.type = RT_INITIALISE_GROUP; |
---|
| 140 | req.groupName = name; |
---|
| 141 | req.listener = listener; |
---|
| 142 | return addRequest(req); |
---|
| 143 | #else |
---|
| 144 | // synchronous |
---|
| 145 | ResourceGroupManager::getSingleton().initialiseResourceGroup(name); |
---|
| 146 | return 0; |
---|
| 147 | #endif |
---|
| 148 | } |
---|
| 149 | //------------------------------------------------------------------------ |
---|
| 150 | BackgroundProcessTicket |
---|
| 151 | ResourceBackgroundQueue::initialiseAllResourceGroups( |
---|
| 152 | ResourceBackgroundQueue::Listener* listener) |
---|
| 153 | { |
---|
| 154 | #if OGRE_THREAD_SUPPORT |
---|
| 155 | if (!mThread && mStartThread) |
---|
| 156 | { |
---|
| 157 | OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, |
---|
| 158 | "Thread not initialised", |
---|
| 159 | "ResourceBackgroundQueue::initialiseAllResourceGroups"); |
---|
| 160 | } |
---|
| 161 | // queue a request |
---|
| 162 | Request req; |
---|
| 163 | req.type = RT_INITIALISE_ALL_GROUPS; |
---|
| 164 | req.listener = listener; |
---|
| 165 | return addRequest(req); |
---|
| 166 | #else |
---|
| 167 | // synchronous |
---|
| 168 | ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); |
---|
| 169 | return 0; |
---|
| 170 | #endif |
---|
| 171 | } |
---|
| 172 | //------------------------------------------------------------------------ |
---|
| 173 | BackgroundProcessTicket ResourceBackgroundQueue::loadResourceGroup( |
---|
| 174 | const String& name, ResourceBackgroundQueue::Listener* listener) |
---|
| 175 | { |
---|
| 176 | #if OGRE_THREAD_SUPPORT |
---|
| 177 | if (!mThread && mStartThread) |
---|
| 178 | { |
---|
| 179 | OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, |
---|
| 180 | "Thread not initialised", |
---|
| 181 | "ResourceBackgroundQueue::loadResourceGroup"); |
---|
| 182 | } |
---|
| 183 | // queue a request |
---|
| 184 | Request req; |
---|
| 185 | req.type = RT_LOAD_GROUP; |
---|
| 186 | req.groupName = name; |
---|
| 187 | req.listener = listener; |
---|
| 188 | return addRequest(req); |
---|
| 189 | #else |
---|
| 190 | // synchronous |
---|
| 191 | ResourceGroupManager::getSingleton().loadResourceGroup(name); |
---|
| 192 | return 0; |
---|
| 193 | #endif |
---|
| 194 | } |
---|
| 195 | //------------------------------------------------------------------------ |
---|
| 196 | BackgroundProcessTicket ResourceBackgroundQueue::load( |
---|
| 197 | const String& resType, const String& name, |
---|
| 198 | const String& group, bool isManual, |
---|
| 199 | ManualResourceLoader* loader, |
---|
| 200 | const NameValuePairList* loadParams, |
---|
| 201 | ResourceBackgroundQueue::Listener* listener) |
---|
| 202 | { |
---|
| 203 | #if OGRE_THREAD_SUPPORT |
---|
| 204 | if (!mThread && mStartThread) |
---|
| 205 | { |
---|
| 206 | OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, |
---|
| 207 | "Thread not initialised", |
---|
| 208 | "ResourceBackgroundQueue::load"); |
---|
| 209 | } |
---|
| 210 | // queue a request |
---|
| 211 | Request req; |
---|
| 212 | req.type = RT_LOAD_RESOURCE; |
---|
| 213 | req.resourceType = resType; |
---|
| 214 | req.resourceName = name; |
---|
| 215 | req.groupName = group; |
---|
| 216 | req.isManual = isManual; |
---|
| 217 | req.loader = loader; |
---|
| 218 | req.loadParams = loadParams; |
---|
| 219 | req.listener = listener; |
---|
| 220 | return addRequest(req); |
---|
| 221 | #else |
---|
| 222 | // synchronous |
---|
| 223 | ResourceManager* rm = |
---|
| 224 | ResourceGroupManager::getSingleton()._getResourceManager(resType); |
---|
| 225 | rm->load(name, group, isManual, loader, loadParams); |
---|
| 226 | return 0; |
---|
| 227 | #endif |
---|
| 228 | } |
---|
| 229 | //--------------------------------------------------------------------- |
---|
| 230 | BackgroundProcessTicket ResourceBackgroundQueue::unload( |
---|
| 231 | const String& resType, const String& name, Listener* listener) |
---|
| 232 | { |
---|
| 233 | #if OGRE_THREAD_SUPPORT |
---|
| 234 | if (!mThread && mStartThread) |
---|
| 235 | { |
---|
| 236 | OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, |
---|
| 237 | "Thread not initialised", |
---|
| 238 | "ResourceBackgroundQueue::unload"); |
---|
| 239 | } |
---|
| 240 | // queue a request |
---|
| 241 | Request req; |
---|
| 242 | req.type = RT_UNLOAD_RESOURCE; |
---|
| 243 | req.resourceType = resType; |
---|
| 244 | req.resourceName = name; |
---|
| 245 | req.listener = listener; |
---|
| 246 | return addRequest(req); |
---|
| 247 | #else |
---|
| 248 | // synchronous |
---|
| 249 | ResourceManager* rm = |
---|
| 250 | ResourceGroupManager::getSingleton()._getResourceManager(resType); |
---|
| 251 | rm->unload(name); |
---|
| 252 | return 0; |
---|
| 253 | #endif |
---|
| 254 | |
---|
| 255 | } |
---|
| 256 | //--------------------------------------------------------------------- |
---|
| 257 | BackgroundProcessTicket ResourceBackgroundQueue::unload( |
---|
| 258 | const String& resType, ResourceHandle handle, Listener* listener) |
---|
| 259 | { |
---|
| 260 | #if OGRE_THREAD_SUPPORT |
---|
| 261 | if (!mThread && mStartThread) |
---|
| 262 | { |
---|
| 263 | OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, |
---|
| 264 | "Thread not initialised", |
---|
| 265 | "ResourceBackgroundQueue::unload"); |
---|
| 266 | } |
---|
| 267 | // queue a request |
---|
| 268 | Request req; |
---|
| 269 | req.type = RT_UNLOAD_RESOURCE; |
---|
| 270 | req.resourceType = resType; |
---|
| 271 | req.resourceHandle = handle; |
---|
| 272 | req.listener = listener; |
---|
| 273 | return addRequest(req); |
---|
| 274 | #else |
---|
| 275 | // synchronous |
---|
| 276 | ResourceManager* rm = |
---|
| 277 | ResourceGroupManager::getSingleton()._getResourceManager(resType); |
---|
| 278 | rm->unload(handle); |
---|
| 279 | return 0; |
---|
| 280 | #endif |
---|
| 281 | |
---|
| 282 | } |
---|
| 283 | //--------------------------------------------------------------------- |
---|
| 284 | BackgroundProcessTicket ResourceBackgroundQueue::unloadResourceGroup( |
---|
| 285 | const String& name, Listener* listener) |
---|
| 286 | { |
---|
| 287 | #if OGRE_THREAD_SUPPORT |
---|
| 288 | if (!mThread && mStartThread) |
---|
| 289 | { |
---|
| 290 | OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, |
---|
| 291 | "Thread not initialised", |
---|
| 292 | "ResourceBackgroundQueue::unloadResourceGroup"); |
---|
| 293 | } |
---|
| 294 | // queue a request |
---|
| 295 | Request req; |
---|
| 296 | req.type = RT_UNLOAD_GROUP; |
---|
| 297 | req.groupName = name; |
---|
| 298 | req.listener = listener; |
---|
| 299 | return addRequest(req); |
---|
| 300 | #else |
---|
| 301 | // synchronous |
---|
| 302 | ResourceGroupManager::getSingleton().unloadResourceGroup(name); |
---|
| 303 | return 0; |
---|
| 304 | #endif |
---|
| 305 | |
---|
| 306 | } |
---|
| 307 | //------------------------------------------------------------------------ |
---|
| 308 | bool ResourceBackgroundQueue::isProcessComplete( |
---|
| 309 | BackgroundProcessTicket ticket) |
---|
| 310 | { |
---|
| 311 | // Lock |
---|
| 312 | OGRE_LOCK_AUTO_MUTEX |
---|
| 313 | |
---|
| 314 | return mRequestTicketMap.find(ticket) == mRequestTicketMap.end(); |
---|
| 315 | } |
---|
| 316 | //------------------------------------------------------------------------ |
---|
| 317 | #if OGRE_THREAD_SUPPORT |
---|
| 318 | BackgroundProcessTicket ResourceBackgroundQueue::addRequest(Request& req) |
---|
| 319 | { |
---|
| 320 | // Lock |
---|
| 321 | OGRE_LOCK_AUTO_MUTEX |
---|
| 322 | |
---|
| 323 | req.ticketID = ++mNextTicketID; |
---|
| 324 | mRequestQueue.push_back(req); |
---|
| 325 | Request* requestInList = &(mRequestQueue.back()); |
---|
| 326 | mRequestTicketMap[req.ticketID] = requestInList; |
---|
| 327 | |
---|
| 328 | // Notify to wake up loading thread |
---|
| 329 | OGRE_THREAD_NOTIFY_ONE(mCondition) |
---|
| 330 | |
---|
| 331 | return req.ticketID; |
---|
| 332 | } |
---|
| 333 | //------------------------------------------------------------------------ |
---|
| 334 | void ResourceBackgroundQueue::threadFunc(void) |
---|
| 335 | { |
---|
| 336 | // Background thread implementation |
---|
| 337 | // Static (since no params allowed), so get instance |
---|
| 338 | ResourceBackgroundQueue& queueInstance = |
---|
| 339 | ResourceBackgroundQueue::getSingleton(); |
---|
| 340 | |
---|
| 341 | LogManager::getSingleton().logMessage("ResourceBackgroundQueue - thread starting."); |
---|
| 342 | |
---|
| 343 | // Initialise the thread |
---|
| 344 | queueInstance._initThread(); |
---|
| 345 | |
---|
| 346 | // Spin forever until we're told to shut down |
---|
| 347 | while (!queueInstance.mShuttingDown) |
---|
| 348 | { |
---|
| 349 | // Our thread will just wait when there is nothing on the queue |
---|
| 350 | // _doNextQueuedBackgroundProcess won't do this since the thread |
---|
| 351 | // may be shared |
---|
| 352 | |
---|
| 353 | // Manual scope block just to define scope of lock |
---|
| 354 | { |
---|
| 355 | // Lock; note that 'mCondition.wait()' will free the lock |
---|
| 356 | boost::recursive_mutex::scoped_lock queueLock( |
---|
| 357 | queueInstance.OGRE_AUTO_MUTEX_NAME); |
---|
| 358 | if (queueInstance.mRequestQueue.empty()) |
---|
| 359 | { |
---|
| 360 | // frees lock and suspends the thread |
---|
| 361 | queueInstance.mCondition.wait(queueLock); |
---|
| 362 | } |
---|
| 363 | // When we get back here, it's because we've been notified |
---|
| 364 | // and thus the thread as been woken up. Lock has also been |
---|
| 365 | // re-acquired. |
---|
| 366 | } // release lock so queueing can be done while we process one request |
---|
| 367 | |
---|
| 368 | queueInstance._doNextQueuedBackgroundProcess(); |
---|
| 369 | |
---|
| 370 | |
---|
| 371 | } |
---|
| 372 | |
---|
| 373 | LogManager::getSingleton().logMessage("ResourceBackgroundQueue - thread stopped."); |
---|
| 374 | |
---|
| 375 | |
---|
| 376 | |
---|
| 377 | } |
---|
| 378 | #endif |
---|
| 379 | //----------------------------------------------------------------------- |
---|
| 380 | void ResourceBackgroundQueue::_initThread() |
---|
| 381 | { |
---|
| 382 | // Register the calling thread with RenderSystem |
---|
| 383 | // Note how we assume only one thread is processing the queue |
---|
| 384 | Root::getSingleton().getRenderSystem()->registerThread(); |
---|
| 385 | { |
---|
| 386 | // notify waiting thread(s) |
---|
| 387 | OGRE_LOCK_MUTEX(initMutex) |
---|
| 388 | OGRE_THREAD_NOTIFY_ALL(initSync) |
---|
| 389 | } |
---|
| 390 | |
---|
| 391 | } |
---|
| 392 | //----------------------------------------------------------------------- |
---|
| 393 | bool ResourceBackgroundQueue::_doNextQueuedBackgroundProcess() |
---|
| 394 | { |
---|
| 395 | |
---|
| 396 | Request* req; |
---|
| 397 | // Manual scope block just to define scope of lock |
---|
| 398 | { |
---|
| 399 | OGRE_LOCK_AUTO_MUTEX |
---|
| 400 | // return false if nothing in the queue |
---|
| 401 | if (mRequestQueue.empty()) |
---|
| 402 | return false; |
---|
| 403 | |
---|
| 404 | // Process one request |
---|
| 405 | req = &(mRequestQueue.front()); |
---|
| 406 | } // release lock so queueing can be done while we process one request |
---|
| 407 | // use of std::list means that references guarateed to remain valid |
---|
| 408 | // we only allow one background thread |
---|
| 409 | |
---|
| 410 | ResourceManager* rm = 0; |
---|
| 411 | switch (req->type) |
---|
| 412 | { |
---|
| 413 | case RT_INITIALISE_GROUP: |
---|
| 414 | ResourceGroupManager::getSingleton().initialiseResourceGroup( |
---|
| 415 | req->groupName); |
---|
| 416 | break; |
---|
| 417 | case RT_INITIALISE_ALL_GROUPS: |
---|
| 418 | ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); |
---|
| 419 | break; |
---|
| 420 | case RT_LOAD_GROUP: |
---|
| 421 | ResourceGroupManager::getSingleton().loadResourceGroup( |
---|
| 422 | req->groupName); |
---|
| 423 | break; |
---|
| 424 | case RT_UNLOAD_GROUP: |
---|
| 425 | ResourceGroupManager::getSingleton().unloadResourceGroup( |
---|
| 426 | req->groupName); |
---|
| 427 | break; |
---|
| 428 | case RT_LOAD_RESOURCE: |
---|
| 429 | rm = ResourceGroupManager::getSingleton()._getResourceManager( |
---|
| 430 | req->resourceType); |
---|
| 431 | rm->load(req->resourceName, req->groupName, req->isManual, |
---|
| 432 | req->loader, req->loadParams); |
---|
| 433 | break; |
---|
| 434 | case RT_UNLOAD_RESOURCE: |
---|
| 435 | rm = ResourceGroupManager::getSingleton()._getResourceManager( |
---|
| 436 | req->resourceType); |
---|
| 437 | if (req->resourceName.empty()) |
---|
| 438 | rm->unload(req->resourceHandle); |
---|
| 439 | else |
---|
| 440 | rm->unload(req->resourceName); |
---|
| 441 | break; |
---|
| 442 | case RT_SHUTDOWN: |
---|
| 443 | // That's all folks |
---|
| 444 | #if OGRE_THREAD_SUPPORT |
---|
| 445 | mShuttingDown = true; |
---|
| 446 | Root::getSingleton().getRenderSystem()->unregisterThread(); |
---|
| 447 | #endif |
---|
| 448 | break; |
---|
| 449 | }; |
---|
| 450 | |
---|
| 451 | // Queue notification (don't do shutdown since not needed & listeners |
---|
| 452 | // might be being destroyed too |
---|
| 453 | if (req->listener && req->type != RT_SHUTDOWN) |
---|
| 454 | { |
---|
| 455 | // Fire in-thread notification first |
---|
| 456 | req->listener->operationCompletedInThread(req->ticketID); |
---|
| 457 | // Then queue main thread notification |
---|
| 458 | queueFireBackgroundOperationComplete(req->listener, req->ticketID); |
---|
| 459 | } |
---|
| 460 | |
---|
| 461 | |
---|
| 462 | { |
---|
| 463 | // re-lock to consume completed request |
---|
| 464 | OGRE_LOCK_AUTO_MUTEX |
---|
| 465 | |
---|
| 466 | // Consume the ticket |
---|
| 467 | mRequestTicketMap.erase(req->ticketID); |
---|
| 468 | mRequestQueue.pop_front(); |
---|
| 469 | } |
---|
| 470 | |
---|
| 471 | return true; |
---|
| 472 | |
---|
| 473 | } |
---|
| 474 | //----------------------------------------------------------------------- |
---|
| 475 | void ResourceBackgroundQueue::_queueFireBackgroundLoadingComplete( |
---|
| 476 | Resource::Listener* listener, Resource* res) |
---|
| 477 | { |
---|
| 478 | OGRE_LOCK_MUTEX(mNotificationQueueMutex); |
---|
| 479 | mNotificationQueue.push_back(QueuedNotification(listener, res)); |
---|
| 480 | |
---|
| 481 | } |
---|
| 482 | //----------------------------------------------------------------------- |
---|
| 483 | void ResourceBackgroundQueue::queueFireBackgroundOperationComplete( |
---|
| 484 | ResourceBackgroundQueue::Listener* listener, BackgroundProcessTicket ticket) |
---|
| 485 | { |
---|
| 486 | OGRE_LOCK_MUTEX(mNotificationQueueMutex); |
---|
| 487 | mNotificationQueue.push_back(QueuedNotification(listener, ticket)); |
---|
| 488 | } |
---|
| 489 | //----------------------------------------------------------------------- |
---|
| 490 | void ResourceBackgroundQueue::_fireBackgroundLoadingComplete() |
---|
| 491 | { |
---|
| 492 | OGRE_LOCK_MUTEX(mNotificationQueueMutex); |
---|
| 493 | for (NotificationQueue::iterator i = mNotificationQueue.begin(); |
---|
| 494 | i != mNotificationQueue.end(); ++i) |
---|
| 495 | { |
---|
| 496 | if (i->resource) |
---|
| 497 | i->resourceListener->backgroundLoadingComplete(i->resource); |
---|
| 498 | else |
---|
| 499 | i->opListener->operationCompleted(i->ticket); |
---|
| 500 | } |
---|
| 501 | mNotificationQueue.clear(); |
---|
| 502 | |
---|
| 503 | } |
---|
| 504 | //------------------------------------------------------------------------ |
---|
| 505 | |
---|
| 506 | } |
---|
| 507 | |
---|
| 508 | |
---|
| 509 | |
---|