| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- /************************************************************************************
- Filename : OVR_System.cpp
- Content : General kernel initialization/cleanup, including that
- of the memory allocator.
- Created : September 19, 2012
- Notes :
- Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
- Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
- you may not use the Oculus VR Rift SDK except in compliance with the License,
- which is provided at the time of installation or download, or which
- otherwise accompanies this software in either electronic or hard copy form.
- You may obtain a copy of the License at
- http://www.oculusvr.com/licenses/LICENSE-3.2
- Unless required by applicable law or agreed to in writing, the Oculus VR SDK
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ************************************************************************************/
- #include "OVR_System.h"
- #include "OVR_Threads.h"
- #include "OVR_Timer.h"
- #include "OVR_DebugHelp.h"
- #include <new>
- #if defined(_MSC_VER)
- #include <new.h>
- #else
- #include <new>
- #endif
- #ifdef OVR_OS_MS
- #pragma warning(push, 0)
- #include "OVR_Win32_IncludeWindows.h" // GetModuleHandleEx
- #pragma warning(pop)
- #endif
- namespace OVR {
- //-----------------------------------------------------------------------------
- // Initialization/Shutdown state
- // If true, then Destroy() was called and is in the process of executing
- // Added to fix race condition if thread is started after the call to System::Destroy()
- static bool ShuttingDown = false;
- //-----------------------------------------------------------------------------
- // Initialization/Shutdown Callbacks
- static SystemSingletonInternal *SystemShutdownListenerList = nullptr; // Points to the most recent SystemSingletonInternal added to the list.
- static Lock& GetSSILock()
- { // Put listLock in a function so that it can be constructed on-demand.
- static Lock listLock; // Will construct on the first usage. However, the guarding of this construction is not thread-safe
- return listLock; // under all compilers. However, since we are initially calling this on startup before other threads
- } // could possibly exist, the first usage of this will be before other threads exist.
- void SystemSingletonInternal::RegisterDestroyCallback()
- {
- GetSSILock().DoLock();
- if (ShuttingDown)
- {
- GetSSILock().Unlock();
- OnThreadDestroy();
- }
- else
- {
- GetSSILock().Unlock();
- // Insert the listener at the front of the list (top of the stack). This is an analogue of a C++ forward_list::push_front or stack::push.
- NextShutdownSingleton = SystemShutdownListenerList;
- SystemShutdownListenerList = this;
- }
- }
- //-----------------------------------------------------------------------------
- // System
- static int System_Init_Count = 0;
- #if defined(_MSC_VER)
- // This allows us to throw OVR::bad_alloc instead of std::bad_alloc, which provides less information.
- int OVRNewFailureHandler(size_t /*size*/)
- {
- throw OVR::bad_alloc();
- // Disabled because otherwise a compiler warning is generated regarding unreachable code.
- //return 0; // A return value of 0 tells the Standard Library to not retry the allocation.
- }
- #else
- // This allows us to throw OVR::bad_alloc instead of std::bad_alloc, which provides less information.
- void OVRNewFailureHandler()
- {
- throw OVR::bad_alloc();
- }
- #endif
- // Initializes System core, installing allocator.
- void System::Init(Log* log)
- {
- #if defined(_MSC_VER)
- // Make it so that failure of the C malloc family of functions results in the same behavior as C++ operator new failure.
- // This allows us to throw exceptions for malloc usage the same as for operator new bad_alloc.
- _set_new_mode(1);
- // Tells the standard library to direct new (and malloc) failures to us. Normally we wouldn't need to do this, as the
- // C++ Standard Library already throws std::bad_alloc on operator new failure. The problem is that the Standard Library doesn't
- // throw std::bad_alloc upon malloc failure, and we can only intercept malloc failure via this means. _set_new_handler specifies
- // a global handler for the current running Standard Library. If the Standard Library is being dynamically linked instead
- // of statically linked, then this is a problem because a call to _set_new_handler would override anything the application
- // has already set.
- _set_new_handler(OVRNewFailureHandler);
- #else
- // This allows us to throw OVR::bad_alloc instead of std::bad_alloc, which provides less information.
- // Question: Does this set the handler for all threads or just the current thread? The C++ Standard doesn't
- // explicitly state this, though it may be implied from other parts of the Standard.
- std::set_new_handler(OVRNewFailureHandler);
- #endif
- if (++System_Init_Count == 1)
- {
- Log::SetGlobalLog(log);
- Timer::initializeTimerSystem();
- }
- else
- {
- OVR_DEBUG_LOG(("[System] Init recursively called; depth = %d", System_Init_Count));
- }
- }
- void System::Destroy()
- {
- GetSSILock().DoLock();
- ShuttingDown = true;
- GetSSILock().Unlock();
- if (--System_Init_Count == 0)
- {
- // Invoke all of the post-finish callbacks (normal case)
- for (SystemSingletonInternal *listener = SystemShutdownListenerList; listener; listener = listener->NextShutdownSingleton)
- {
- listener->OnThreadDestroy();
- }
- #ifdef OVR_ENABLE_THREADS
- // Wait for all threads to finish; this must be done so that memory
- // allocator and all destructors finalize correctly.
- Thread::FinishAllThreads();
- #endif
- // Invoke all of the post-finish callbacks (normal case)
- for (SystemSingletonInternal* next, *listener = SystemShutdownListenerList; listener; listener = next)
- {
- next = listener->NextShutdownSingleton;
- listener->OnSystemDestroy();
- }
- SystemShutdownListenerList = nullptr;
- Timer::shutdownTimerSystem();
- Log::SetGlobalLog(Log::GetDefaultLog());
- if (Allocator::IsTrackingLeaks())
- {
- int ovrLeakCount = Allocator::DumpMemory();
- OVR_ASSERT(ovrLeakCount == 0);
- if (ovrLeakCount == 0)
- {
- OVR_DEBUG_LOG(("[System] No OVR object leaks detected."));
- }
- }
- }
- else
- {
- OVR_DEBUG_LOG(("[System] Destroy recursively called; depth = %d", System_Init_Count));
- }
- GetSSILock().DoLock();
- ShuttingDown = false;
- GetSSILock().Unlock();
- }
- // Returns 'true' if system was properly initialized.
- bool System::IsInitialized()
- {
- return System_Init_Count > 0;
- }
- } // namespace OVR
|