init - 初始化项目
This commit is contained in:
116
3rdparty/openexr/IlmThread/IlmThread.cpp
vendored
Normal file
116
3rdparty/openexr/IlmThread/IlmThread.cpp
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Thread -- this file contains two implementations of thread:
|
||||
// - dummy implementation for platforms that do not support threading
|
||||
// when OPENEXR_FORCE_CXX03 is on
|
||||
// - c++11 and newer version
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
#include "IlmThread.h"
|
||||
#include "Iex.h"
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
#ifndef ILMBASE_FORCE_CXX03
|
||||
//-----------------------------------------------------------------------------
|
||||
// C++11 and newer implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
bool
|
||||
supportsThreads ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Thread::Thread ()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread ()
|
||||
{
|
||||
// hopefully the thread has basically exited and we are just
|
||||
// cleaning up, because run is a virtual function, so the v-table
|
||||
// has already been partly destroyed...
|
||||
if ( _thread.joinable () )
|
||||
_thread.join ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Thread::start ()
|
||||
{
|
||||
_thread = std::thread (&Thread::run, this);
|
||||
}
|
||||
|
||||
#else
|
||||
# if !defined (_WIN32) &&!(_WIN64) && !(HAVE_PTHREAD)
|
||||
//-----------------------------------------------------------------------------
|
||||
// OPENEXR_FORCE_CXX03 with no windows / pthread support
|
||||
//-----------------------------------------------------------------------------
|
||||
bool
|
||||
supportsThreads ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Thread::Thread ()
|
||||
{
|
||||
throw IEX_NAMESPACE::NoImplExc ("Threads not supported on this platform.");
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread ()
|
||||
{
|
||||
throw IEX_NAMESPACE::NoImplExc ("Threads not supported on this platform.");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Thread::start ()
|
||||
{
|
||||
throw IEX_NAMESPACE::NoImplExc ("Threads not supported on this platform.");
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
153
3rdparty/openexr/IlmThread/IlmThread.h
vendored
Normal file
153
3rdparty/openexr/IlmThread/IlmThread.h
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_ILM_THREAD_H
|
||||
#define INCLUDED_ILM_THREAD_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Thread
|
||||
//
|
||||
// Class Thread is a portable interface to a system-dependent thread
|
||||
// primitive. In order to make a thread actually do something useful,
|
||||
// you must derive a subclass from class Thread and implement the
|
||||
// run() function. If the operating system supports threading then
|
||||
// the run() function will be executed int a new thread.
|
||||
//
|
||||
// The actual creation of the thread is done by the start() routine
|
||||
// which then calls the run() function. In general the start()
|
||||
// routine should be called from the constructor of the derived class.
|
||||
//
|
||||
// The base-class thread destructor will join/destroy the thread.
|
||||
//
|
||||
// IMPORTANT: Due to the mechanisms that encapsulate the low-level
|
||||
// threading primitives in a C++ class there is a race condition
|
||||
// with code resembling the following:
|
||||
//
|
||||
// {
|
||||
// WorkerThread myThread;
|
||||
// } // myThread goes out of scope, is destroyed
|
||||
// // and the thread is joined
|
||||
//
|
||||
// The race is between the parent thread joining the child thread
|
||||
// in the destructor of myThread, and the run() function in the
|
||||
// child thread. If the destructor gets executed first then run()
|
||||
// will be called with an invalid "this" pointer.
|
||||
//
|
||||
// This issue can be fixed by using a Semaphore to keep track of
|
||||
// whether the run() function has already been called. You can
|
||||
// include a Semaphore member variable within your derived class
|
||||
// which you post() on in the run() function, and wait() on in the
|
||||
// destructor before the thread is joined. Alternatively you could
|
||||
// do something like this:
|
||||
//
|
||||
// Semaphore runStarted;
|
||||
//
|
||||
// void WorkerThread::run ()
|
||||
// {
|
||||
// runStarted.post()
|
||||
// // do some work
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// WorkerThread myThread;
|
||||
// runStarted.wait (); // ensure that we have started
|
||||
// // the run function
|
||||
// } // myThread goes out of scope, is destroyed
|
||||
// // and the thread is joined
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
#include "IlmThreadExport.h"
|
||||
#include "IlmThreadNamespace.h"
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
# if defined _WIN32 || defined _WIN64
|
||||
# ifdef NOMINMAX
|
||||
# undef NOMINMAX
|
||||
# endif
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
# include <process.h>
|
||||
# elif HAVE_PTHREAD
|
||||
# include <pthread.h>
|
||||
# endif
|
||||
#else
|
||||
# include <thread>
|
||||
#endif
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER
|
||||
|
||||
//
|
||||
// Query function to determine if the current platform supports
|
||||
// threads AND this library was compiled with threading enabled.
|
||||
//
|
||||
|
||||
ILMTHREAD_EXPORT bool supportsThreads ();
|
||||
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
|
||||
ILMTHREAD_EXPORT Thread ();
|
||||
ILMTHREAD_EXPORT virtual ~Thread ();
|
||||
|
||||
ILMTHREAD_EXPORT void start ();
|
||||
ILMTHREAD_EXPORT virtual void run () = 0;
|
||||
|
||||
private:
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
# if defined _WIN32 || defined _WIN64
|
||||
HANDLE _thread;
|
||||
# elif HAVE_PTHREAD
|
||||
pthread_t _thread;
|
||||
# endif
|
||||
void operator = (const Thread& t); // not implemented
|
||||
Thread (const Thread& t); // not implemented
|
||||
#else
|
||||
std::thread _thread;
|
||||
|
||||
Thread &operator= (const Thread& t) = delete;
|
||||
Thread (const Thread& t) = delete;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT
|
||||
|
||||
#endif // INCLUDED_ILM_THREAD_H
|
||||
46
3rdparty/openexr/IlmThread/IlmThreadExport.h
vendored
Normal file
46
3rdparty/openexr/IlmThread/IlmThreadExport.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(OPENEXR_DLL)
|
||||
#if defined(ILMTHREAD_EXPORTS)
|
||||
#define ILMTHREAD_EXPORT __declspec(dllexport)
|
||||
#define ILMTHREAD_EXPORT_CONST extern __declspec(dllexport)
|
||||
#else
|
||||
#define ILMTHREAD_EXPORT __declspec(dllimport)
|
||||
#define ILMTHREAD_EXPORT_CONST extern __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define ILMTHREAD_EXPORT
|
||||
#define ILMTHREAD_EXPORT_CONST extern const
|
||||
#endif
|
||||
60
3rdparty/openexr/IlmThread/IlmThreadForward.h
vendored
Normal file
60
3rdparty/openexr/IlmThread/IlmThreadForward.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_ILMTHREADFORWARD_H
|
||||
#define INCLUDED_ILMTHREADFORWARD_H
|
||||
|
||||
#include "IlmThreadNamespace.h"
|
||||
|
||||
#ifndef ILMBASE_FORCE_CXX03
|
||||
namespace std { class mutex; }
|
||||
#endif
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER
|
||||
|
||||
class Thread;
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
class Mutex;
|
||||
#else
|
||||
using Mutex = std::mutex;
|
||||
#endif
|
||||
class Lock;
|
||||
class ThreadPool;
|
||||
class Task;
|
||||
class TaskGroup;
|
||||
class Semaphore;
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT
|
||||
|
||||
#endif // INCLUDED_ILMTHREADFORWARD_H
|
||||
60
3rdparty/openexr/IlmThread/IlmThreadMutex.cpp
vendored
Normal file
60
3rdparty/openexr/IlmThread/IlmThreadMutex.cpp
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Mutex, class Lock -- dummy implementation
|
||||
// for platforms that do not support threading
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
# if !defined (_WIN32) && !(_WIN64) && !(HAVE_PTHREAD)
|
||||
# include "IlmThreadMutex.h"
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
|
||||
Mutex::Mutex () {}
|
||||
Mutex::~Mutex () {}
|
||||
void Mutex::lock () const {}
|
||||
void Mutex::unlock () const {}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
# endif
|
||||
#endif
|
||||
180
3rdparty/openexr/IlmThread/IlmThreadMutex.h
vendored
Normal file
180
3rdparty/openexr/IlmThread/IlmThreadMutex.h
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_ILM_THREAD_MUTEX_H
|
||||
#define INCLUDED_ILM_THREAD_MUTEX_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Mutex, class Lock
|
||||
//
|
||||
// Class Mutex is a wrapper for a system-dependent mutual exclusion
|
||||
// mechanism. Actual locking and unlocking of a Mutex object must
|
||||
// be performed using an instance of a Lock (defined below).
|
||||
//
|
||||
// Class lock provides safe locking and unlocking of mutexes even in
|
||||
// the presence of C++ exceptions. Constructing a Lock object locks
|
||||
// the mutex; destroying the Lock unlocks the mutex.
|
||||
//
|
||||
// Lock objects are not themselves thread-safe. You should never
|
||||
// share a Lock object among multiple threads.
|
||||
//
|
||||
// Typical usage:
|
||||
//
|
||||
// Mutex mtx; // Create a Mutex object that is visible
|
||||
// //to multiple threads
|
||||
//
|
||||
// ... // create some threads
|
||||
//
|
||||
// // Then, within each thread, construct a critical section like so:
|
||||
//
|
||||
// {
|
||||
// Lock lock (mtx); // Lock constructor locks the mutex
|
||||
// ... // do some computation on shared data
|
||||
// } // leaving the block unlocks the mutex
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmThreadExport.h"
|
||||
#include "IlmBaseConfig.h"
|
||||
#include "IlmThreadNamespace.h"
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
# if defined _WIN32 || defined _WIN64
|
||||
# ifdef NOMINMAX
|
||||
# undef NOMINMAX
|
||||
# endif
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
# elif HAVE_PTHREAD
|
||||
# include <pthread.h>
|
||||
# endif
|
||||
#else
|
||||
# include <mutex>
|
||||
#endif
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER
|
||||
|
||||
|
||||
// in c++11, this can just be
|
||||
//
|
||||
// using Mutex = std::mutex;
|
||||
// unfortunately we can't use std::unique_lock as a replacement for Lock since
|
||||
// they have different API.
|
||||
//
|
||||
// if we decide to break the API, we can just
|
||||
//
|
||||
// using Lock = std::lock_guard<std::mutex>;
|
||||
// or
|
||||
// using Lock = std::unique_lock<std::mutex>;
|
||||
//
|
||||
// (or eliminate the type completely and have people use the std library)
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
|
||||
class Lock;
|
||||
|
||||
class ILMTHREAD_EXPORT Mutex
|
||||
{
|
||||
public:
|
||||
|
||||
Mutex ();
|
||||
virtual ~Mutex ();
|
||||
|
||||
private:
|
||||
|
||||
void lock () const;
|
||||
void unlock () const;
|
||||
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
mutable CRITICAL_SECTION _mutex;
|
||||
#elif HAVE_PTHREAD
|
||||
mutable pthread_mutex_t _mutex;
|
||||
#endif
|
||||
|
||||
void operator = (const Mutex& M); // not implemented
|
||||
Mutex (const Mutex& M); // not implemented
|
||||
|
||||
friend class Lock;
|
||||
};
|
||||
#else
|
||||
using Mutex = std::mutex;
|
||||
#endif
|
||||
|
||||
class ILMTHREAD_EXPORT Lock
|
||||
{
|
||||
public:
|
||||
|
||||
Lock (const Mutex& m, bool autoLock = true):
|
||||
_mutex (const_cast<Mutex &>(m)), _locked (false)
|
||||
{
|
||||
if (autoLock)
|
||||
{
|
||||
_mutex.lock();
|
||||
_locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
~Lock ()
|
||||
{
|
||||
if (_locked)
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
void acquire ()
|
||||
{
|
||||
_mutex.lock();
|
||||
_locked = true;
|
||||
}
|
||||
|
||||
void release ()
|
||||
{
|
||||
_mutex.unlock();
|
||||
_locked = false;
|
||||
}
|
||||
|
||||
bool locked ()
|
||||
{
|
||||
return _locked;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Mutex & _mutex;
|
||||
bool _locked;
|
||||
};
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT
|
||||
|
||||
#endif // INCLUDED_ILM_THREAD_MUTEX_H
|
||||
87
3rdparty/openexr/IlmThread/IlmThreadMutexPosix.cpp
vendored
Normal file
87
3rdparty/openexr/IlmThread/IlmThreadMutexPosix.cpp
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Mutex -- implementation for
|
||||
// platforms that support Posix threads
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
# if HAVE_PTHREAD
|
||||
|
||||
# include "IlmThreadMutex.h"
|
||||
# include "Iex.h"
|
||||
# include <assert.h>
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
|
||||
Mutex::Mutex ()
|
||||
{
|
||||
if (int error = ::pthread_mutex_init (&_mutex, 0))
|
||||
IEX_INTERNAL_NAMESPACE::throwErrnoExc ("Cannot initialize mutex (%T).", error);
|
||||
}
|
||||
|
||||
|
||||
Mutex::~Mutex ()
|
||||
{
|
||||
int error = ::pthread_mutex_destroy (&_mutex);
|
||||
assert (error == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Mutex::lock () const
|
||||
{
|
||||
if (int error = ::pthread_mutex_lock (&_mutex))
|
||||
IEX_INTERNAL_NAMESPACE::throwErrnoExc ("Cannot lock mutex (%T).", error);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Mutex::unlock () const
|
||||
{
|
||||
if (int error = ::pthread_mutex_unlock (&_mutex))
|
||||
IEX_INTERNAL_NAMESPACE::throwErrnoExc ("Cannot unlock mutex (%T).", error);
|
||||
}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
# endif
|
||||
#endif
|
||||
78
3rdparty/openexr/IlmThread/IlmThreadMutexWin32.cpp
vendored
Normal file
78
3rdparty/openexr/IlmThread/IlmThreadMutexWin32.cpp
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Mutex -- implementation for Windows
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
# include "IlmThreadMutex.h"
|
||||
# include "Iex.h"
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
|
||||
Mutex::Mutex ()
|
||||
{
|
||||
::InitializeCriticalSection (&_mutex);
|
||||
}
|
||||
|
||||
|
||||
Mutex::~Mutex ()
|
||||
{
|
||||
::DeleteCriticalSection (&_mutex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Mutex::lock () const
|
||||
{
|
||||
::EnterCriticalSection (&_mutex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Mutex::unlock () const
|
||||
{
|
||||
::LeaveCriticalSection (&_mutex);
|
||||
}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
#endif
|
||||
114
3rdparty/openexr/IlmThread/IlmThreadNamespace.h
vendored
Normal file
114
3rdparty/openexr/IlmThread/IlmThreadNamespace.h
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_ILMTHREADNAMESPACE_H
|
||||
#define INCLUDED_ILMTHREADNAMESPACE_H
|
||||
|
||||
//
|
||||
// The purpose of this file is to make it possible to specify an
|
||||
// ILMTHREAD_INTERNAL_NAMESPACE as a preprocessor definition and have all of
|
||||
// the IlmThread symbols defined within that namespace rather than the
|
||||
// standard IlmThread namespace. Those symbols are made available to client
|
||||
// code through the ILMTHREAD_NAMESPACE in addition to the
|
||||
// ILMTHREAD_INTERNAL_NAMESPACE.
|
||||
//
|
||||
// To ensure source code compatibility, the ILMTHREAD_NAMESPACE defaults to
|
||||
// IlmThread and then "using namespace ILMTHREAD_INTERNAL_NAMESPACE;" brings
|
||||
// all of the declarations from the ILMTHREAD_INTERNAL_NAMESPACE into the
|
||||
// ILMTHREAD_NAMESPACE. This means that client code can continue to use
|
||||
// syntax like IlmThread::Thread, but at link time it will resolve to a
|
||||
// mangled symbol based on the ILMTHREAD_INTERNAL_NAMESPACE.
|
||||
//
|
||||
// As an example, if one needed to build against a newer version of IlmThread
|
||||
// and have it run alongside an older version in the same application, it is
|
||||
// now possible to use an internal namespace to prevent collisions between
|
||||
// the older versions of IlmThread symbols and the newer ones. To do this,
|
||||
// the following could be defined at build time:
|
||||
//
|
||||
// ILMTHREAD_INTERNAL_NAMESPACE = IlmThread_v2
|
||||
//
|
||||
// This means that declarations inside IlmThread headers look like this
|
||||
// (after the preprocessor has done its work):
|
||||
//
|
||||
// namespace IlmThread_v2 {
|
||||
// ...
|
||||
// class declarations
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// namespace IlmThread {
|
||||
// using namespace IlmThread_v2;
|
||||
// }
|
||||
//
|
||||
|
||||
//
|
||||
// Open Source version of this file pulls in the IlmBaseConfig.h file
|
||||
// for the configure time options.
|
||||
//
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#ifndef ILMTHREAD_NAMESPACE
|
||||
#define ILMTHREAD_NAMESPACE IlmThread
|
||||
#endif
|
||||
|
||||
#ifndef ILMTHREAD_INTERNAL_NAMESPACE
|
||||
#define ILMTHREAD_INTERNAL_NAMESPACE ILMTHREAD_NAMESPACE
|
||||
#endif
|
||||
|
||||
//
|
||||
// We need to be sure that we import the internal namespace into the public one.
|
||||
// To do this, we use the small bit of code below which initially defines
|
||||
// ILMTHREAD_INTERNAL_NAMESPACE (so it can be referenced) and then defines
|
||||
// ILMTHREAD_NAMESPACE and pulls the internal symbols into the public
|
||||
// namespace.
|
||||
//
|
||||
|
||||
namespace ILMTHREAD_INTERNAL_NAMESPACE {}
|
||||
namespace ILMTHREAD_NAMESPACE {
|
||||
using namespace ILMTHREAD_INTERNAL_NAMESPACE;
|
||||
}
|
||||
|
||||
//
|
||||
// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that
|
||||
// future extension to the namespace mechanism is possible without changing
|
||||
// project source code.
|
||||
//
|
||||
|
||||
#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER namespace ILMTHREAD_INTERNAL_NAMESPACE {
|
||||
#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT }
|
||||
|
||||
#define ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER namespace ILMTHREAD_INTERNAL_NAMESPACE {
|
||||
#define ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT }
|
||||
|
||||
#endif // INCLUDED_ILMTHREADNAMESPACE_H
|
||||
851
3rdparty/openexr/IlmThread/IlmThreadPool.cpp
vendored
Normal file
851
3rdparty/openexr/IlmThread/IlmThreadPool.cpp
vendored
Normal file
@@ -0,0 +1,851 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Task, class ThreadPool, class TaskGroup
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmThread.h"
|
||||
#include "IlmThreadMutex.h"
|
||||
#include "IlmThreadSemaphore.h"
|
||||
#include "IlmThreadPool.h"
|
||||
#include "Iex.h"
|
||||
#include <vector>
|
||||
#ifndef ILMBASE_FORCE_CXX03
|
||||
# include <memory>
|
||||
# include <atomic>
|
||||
# include <thread>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
#if defined(__GNU_LIBRARY__) && ( __GLIBC__ < 2 || ( __GLIBC__ == 2 && __GLIBC_MINOR__ < 21 ) )
|
||||
# define ENABLE_SEM_DTOR_WORKAROUND
|
||||
#endif
|
||||
|
||||
struct TaskGroup::Data
|
||||
{
|
||||
Data ();
|
||||
~Data ();
|
||||
|
||||
void addTask () ;
|
||||
void removeTask ();
|
||||
#ifndef ILMBASE_FORCE_CXX03
|
||||
std::atomic<int> numPending;
|
||||
#else
|
||||
int numPending; // number of pending tasks to still execute
|
||||
#endif
|
||||
Semaphore isEmpty; // used to signal that the taskgroup is empty
|
||||
#if defined(ENABLE_SEM_DTOR_WORKAROUND) || defined(ILMBASE_FORCE_CXX03)
|
||||
// this mutex is also used to lock numPending in the legacy c++ mode...
|
||||
Mutex dtorMutex; // used to work around the glibc bug:
|
||||
// http://sources.redhat.com/bugzilla/show_bug.cgi?id=12674
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct ThreadPool::Data
|
||||
{
|
||||
typedef ThreadPoolProvider *TPPointer;
|
||||
|
||||
Data ();
|
||||
~Data();
|
||||
|
||||
struct SafeProvider
|
||||
{
|
||||
SafeProvider (Data *d, ThreadPoolProvider *p) : _data( d ), _ptr( p )
|
||||
{
|
||||
}
|
||||
|
||||
~SafeProvider()
|
||||
{
|
||||
if ( _data )
|
||||
_data->coalesceProviderUse();
|
||||
}
|
||||
SafeProvider (const SafeProvider &o)
|
||||
: _data( o._data ), _ptr( o._ptr )
|
||||
{
|
||||
if ( _data )
|
||||
_data->bumpProviderUse();
|
||||
}
|
||||
SafeProvider &operator= (const SafeProvider &o)
|
||||
{
|
||||
if ( this != &o )
|
||||
{
|
||||
if ( o._data )
|
||||
o._data->bumpProviderUse();
|
||||
if ( _data )
|
||||
_data->coalesceProviderUse();
|
||||
_data = o._data;
|
||||
_ptr = o._ptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#ifndef ILMBASE_FORCE_CXX03
|
||||
SafeProvider( SafeProvider &&o )
|
||||
: _data( o._data ), _ptr( o._ptr )
|
||||
{
|
||||
o._data = nullptr;
|
||||
}
|
||||
SafeProvider &operator=( SafeProvider &&o )
|
||||
{
|
||||
std::swap( _data, o._data );
|
||||
std::swap( _ptr, o._ptr );
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
inline ThreadPoolProvider *get () const
|
||||
{
|
||||
return _ptr;
|
||||
}
|
||||
ThreadPoolProvider *operator-> () const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
Data *_data;
|
||||
ThreadPoolProvider *_ptr;
|
||||
};
|
||||
|
||||
// NB: In C++20, there is full support for atomic shared_ptr, but that is not
|
||||
// yet in use or finalized. Once stabilized, add appropriate usage here
|
||||
inline SafeProvider getProvider ();
|
||||
inline void coalesceProviderUse ();
|
||||
inline void bumpProviderUse ();
|
||||
inline void setProvider (ThreadPoolProvider *p);
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Semaphore provSem;
|
||||
Mutex provMutex;
|
||||
int provUsers;
|
||||
ThreadPoolProvider *provider;
|
||||
ThreadPoolProvider *oldprovider;
|
||||
#else
|
||||
std::atomic<ThreadPoolProvider *> provider;
|
||||
std::atomic<int> provUsers;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class DefaultWorkerThread;
|
||||
|
||||
struct DefaultWorkData
|
||||
{
|
||||
Semaphore taskSemaphore; // threads wait on this for ready tasks
|
||||
mutable Mutex taskMutex; // mutual exclusion for the tasks list
|
||||
vector<Task*> tasks; // the list of tasks to execute
|
||||
|
||||
Semaphore threadSemaphore; // signaled when a thread starts executing
|
||||
mutable Mutex threadMutex; // mutual exclusion for threads list
|
||||
vector<DefaultWorkerThread*> threads; // the list of all threads
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
bool stopping; // flag indicating whether to stop threads
|
||||
mutable Mutex stopMutex; // mutual exclusion for stopping flag
|
||||
#else
|
||||
std::atomic<bool> hasThreads;
|
||||
std::atomic<bool> stopping;
|
||||
#endif
|
||||
|
||||
inline bool stopped () const
|
||||
{
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock lock (stopMutex);
|
||||
return stopping;
|
||||
#else
|
||||
return stopping.load( std::memory_order_relaxed );
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void stop ()
|
||||
{
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock lock (stopMutex);
|
||||
#endif
|
||||
stopping = true;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// class WorkerThread
|
||||
//
|
||||
class DefaultWorkerThread: public Thread
|
||||
{
|
||||
public:
|
||||
|
||||
DefaultWorkerThread (DefaultWorkData* data);
|
||||
|
||||
virtual void run ();
|
||||
|
||||
private:
|
||||
|
||||
DefaultWorkData * _data;
|
||||
};
|
||||
|
||||
|
||||
DefaultWorkerThread::DefaultWorkerThread (DefaultWorkData* data):
|
||||
_data (data)
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DefaultWorkerThread::run ()
|
||||
{
|
||||
//
|
||||
// Signal that the thread has started executing
|
||||
//
|
||||
|
||||
_data->threadSemaphore.post();
|
||||
|
||||
while (true)
|
||||
{
|
||||
//
|
||||
// Wait for a task to become available
|
||||
//
|
||||
|
||||
_data->taskSemaphore.wait();
|
||||
|
||||
{
|
||||
Lock taskLock (_data->taskMutex);
|
||||
|
||||
//
|
||||
// If there is a task pending, pop off the next task in the FIFO
|
||||
//
|
||||
|
||||
if (!_data->tasks.empty())
|
||||
{
|
||||
Task* task = _data->tasks.back();
|
||||
_data->tasks.pop_back();
|
||||
taskLock.release();
|
||||
|
||||
TaskGroup* taskGroup = task->group();
|
||||
task->execute();
|
||||
|
||||
delete task;
|
||||
|
||||
taskGroup->_data->removeTask ();
|
||||
}
|
||||
else if (_data->stopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// class DefaultThreadPoolProvider
|
||||
//
|
||||
class DefaultThreadPoolProvider : public ThreadPoolProvider
|
||||
{
|
||||
public:
|
||||
DefaultThreadPoolProvider(int count);
|
||||
virtual ~DefaultThreadPoolProvider();
|
||||
|
||||
virtual int numThreads() const;
|
||||
virtual void setNumThreads(int count);
|
||||
virtual void addTask(Task *task);
|
||||
|
||||
virtual void finish();
|
||||
|
||||
private:
|
||||
DefaultWorkData _data;
|
||||
};
|
||||
|
||||
DefaultThreadPoolProvider::DefaultThreadPoolProvider (int count)
|
||||
{
|
||||
setNumThreads(count);
|
||||
}
|
||||
|
||||
DefaultThreadPoolProvider::~DefaultThreadPoolProvider ()
|
||||
{
|
||||
finish();
|
||||
}
|
||||
|
||||
int
|
||||
DefaultThreadPoolProvider::numThreads () const
|
||||
{
|
||||
Lock lock (_data.threadMutex);
|
||||
return static_cast<int> (_data.threads.size());
|
||||
}
|
||||
|
||||
void
|
||||
DefaultThreadPoolProvider::setNumThreads (int count)
|
||||
{
|
||||
//
|
||||
// Lock access to thread list and size
|
||||
//
|
||||
|
||||
Lock lock (_data.threadMutex);
|
||||
|
||||
size_t desired = static_cast<size_t>(count);
|
||||
if (desired > _data.threads.size())
|
||||
{
|
||||
//
|
||||
// Add more threads
|
||||
//
|
||||
|
||||
while (_data.threads.size() < desired)
|
||||
_data.threads.push_back (new DefaultWorkerThread (&_data));
|
||||
}
|
||||
else if ((size_t)count < _data.threads.size())
|
||||
{
|
||||
//
|
||||
// Wait until all existing threads are finished processing,
|
||||
// then delete all threads.
|
||||
//
|
||||
finish ();
|
||||
|
||||
//
|
||||
// Add in new threads
|
||||
//
|
||||
|
||||
while (_data.threads.size() < desired)
|
||||
_data.threads.push_back (new DefaultWorkerThread (&_data));
|
||||
}
|
||||
#ifndef ILMBASE_FORCE_CXX03
|
||||
_data.hasThreads = !(_data.threads.empty());
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DefaultThreadPoolProvider::addTask (Task *task)
|
||||
{
|
||||
//
|
||||
// Lock the threads, needed to access numThreads
|
||||
//
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
bool doPush;
|
||||
{
|
||||
Lock lock (_data.threadMutex);
|
||||
doPush = !_data.threads.empty();
|
||||
}
|
||||
#else
|
||||
bool doPush = _data.hasThreads.load( std::memory_order_relaxed );
|
||||
#endif
|
||||
|
||||
if ( doPush )
|
||||
{
|
||||
//
|
||||
// Get exclusive access to the tasks queue
|
||||
//
|
||||
|
||||
{
|
||||
Lock taskLock (_data.taskMutex);
|
||||
|
||||
//
|
||||
// Push the new task into the FIFO
|
||||
//
|
||||
_data.tasks.push_back (task);
|
||||
}
|
||||
|
||||
//
|
||||
// Signal that we have a new task to process
|
||||
//
|
||||
_data.taskSemaphore.post ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// this path shouldn't normally happen since we have the
|
||||
// NullThreadPoolProvider, but just in case...
|
||||
task->execute ();
|
||||
task->group()->_data->removeTask ();
|
||||
delete task;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DefaultThreadPoolProvider::finish ()
|
||||
{
|
||||
_data.stop();
|
||||
|
||||
//
|
||||
// Signal enough times to allow all threads to stop.
|
||||
//
|
||||
// Wait until all threads have started their run functions.
|
||||
// If we do not wait before we destroy the threads then it's
|
||||
// possible that the threads have not yet called their run
|
||||
// functions.
|
||||
// If this happens then the run function will be called off
|
||||
// of an invalid object and we will crash, most likely with
|
||||
// an error like: "pure virtual method called"
|
||||
//
|
||||
|
||||
size_t curT = _data.threads.size();
|
||||
for (size_t i = 0; i != curT; ++i)
|
||||
{
|
||||
_data.taskSemaphore.post();
|
||||
_data.threadSemaphore.wait();
|
||||
}
|
||||
|
||||
//
|
||||
// Join all the threads
|
||||
//
|
||||
for (size_t i = 0; i != curT; ++i)
|
||||
delete _data.threads[i];
|
||||
|
||||
Lock lock1 (_data.taskMutex);
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock lock2 (_data.stopMutex);
|
||||
#endif
|
||||
_data.threads.clear();
|
||||
_data.tasks.clear();
|
||||
|
||||
_data.stopping = false;
|
||||
}
|
||||
|
||||
|
||||
class NullThreadPoolProvider : public ThreadPoolProvider
|
||||
{
|
||||
virtual ~NullThreadPoolProvider() {}
|
||||
virtual int numThreads () const { return 0; }
|
||||
virtual void setNumThreads (int count)
|
||||
{
|
||||
}
|
||||
virtual void addTask (Task *t)
|
||||
{
|
||||
t->execute ();
|
||||
t->group()->_data->removeTask ();
|
||||
delete t;
|
||||
}
|
||||
virtual void finish () {}
|
||||
};
|
||||
|
||||
} //namespace
|
||||
|
||||
|
||||
//
|
||||
// struct TaskGroup::Data
|
||||
//
|
||||
|
||||
TaskGroup::Data::Data (): isEmpty (1), numPending (0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
TaskGroup::Data::~Data ()
|
||||
{
|
||||
//
|
||||
// A TaskGroup acts like an "inverted" semaphore: if the count
|
||||
// is above 0 then waiting on the taskgroup will block. This
|
||||
// destructor waits until the taskgroup is empty before returning.
|
||||
//
|
||||
|
||||
isEmpty.wait ();
|
||||
|
||||
#ifdef ENABLE_SEM_DTOR_WORKAROUND
|
||||
// Update: this was fixed in v. 2.2.21, so this ifdef checks for that
|
||||
//
|
||||
// Alas, given the current bug in glibc we need a secondary
|
||||
// syncronisation primitive here to account for the fact that
|
||||
// destructing the isEmpty Semaphore in this thread can cause
|
||||
// an error for a separate thread that is issuing the post() call.
|
||||
// We are entitled to destruct the semaphore at this point, however,
|
||||
// that post() call attempts to access data out of the associated
|
||||
// memory *after* it has woken the waiting threads, including this one,
|
||||
// potentially leading to invalid memory reads.
|
||||
// http://sources.redhat.com/bugzilla/show_bug.cgi?id=12674
|
||||
|
||||
Lock lock (dtorMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TaskGroup::Data::addTask ()
|
||||
{
|
||||
//
|
||||
// in c++11, we use an atomic to protect numPending to avoid the
|
||||
// extra lock but for c++98, to add the ability for custom thread
|
||||
// pool we add the lock here
|
||||
//
|
||||
#if ILMBASE_FORCE_CXX03
|
||||
Lock lock (dtorMutex);
|
||||
#endif
|
||||
if (numPending++ == 0)
|
||||
isEmpty.wait ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TaskGroup::Data::removeTask ()
|
||||
{
|
||||
// Alas, given the current bug in glibc we need a secondary
|
||||
// syncronisation primitive here to account for the fact that
|
||||
// destructing the isEmpty Semaphore in a separate thread can
|
||||
// cause an error. Issuing the post call here the current libc
|
||||
// implementation attempts to access memory *after* it has woken
|
||||
// waiting threads.
|
||||
// Since other threads are entitled to delete the semaphore the
|
||||
// access to the memory location can be invalid.
|
||||
// http://sources.redhat.com/bugzilla/show_bug.cgi?id=12674
|
||||
// Update: this bug has been fixed, but how do we know which
|
||||
// glibc version we're in?
|
||||
|
||||
// Further update:
|
||||
//
|
||||
// we could remove this if it is a new enough glibc, however
|
||||
// we've changed the API to enable a custom override of a
|
||||
// thread pool. In order to provide safe access to the numPending,
|
||||
// we need the lock anyway, except for c++11 or newer
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock lock (dtorMutex);
|
||||
|
||||
if (--numPending == 0)
|
||||
isEmpty.post ();
|
||||
#else
|
||||
if (--numPending == 0)
|
||||
{
|
||||
#ifdef ENABLE_SEM_DTOR_WORKAROUND
|
||||
Lock lock (dtorMutex);
|
||||
#endif
|
||||
isEmpty.post ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// struct ThreadPool::Data
|
||||
//
|
||||
|
||||
ThreadPool::Data::Data ():
|
||||
provUsers (0), provider (NULL)
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
, oldprovider (NULL)
|
||||
#else
|
||||
#endif
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
ThreadPool::Data::~Data()
|
||||
{
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
provider->finish();
|
||||
#else
|
||||
ThreadPoolProvider *p = provider.load( std::memory_order_relaxed );
|
||||
p->finish();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline ThreadPool::Data::SafeProvider
|
||||
ThreadPool::Data::getProvider ()
|
||||
{
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock provLock( provMutex );
|
||||
++provUsers;
|
||||
return SafeProvider( this, provider );
|
||||
#else
|
||||
provUsers.fetch_add( 1, std::memory_order_relaxed );
|
||||
return SafeProvider( this, provider.load( std::memory_order_relaxed ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
ThreadPool::Data::coalesceProviderUse ()
|
||||
{
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock provLock( provMutex );
|
||||
--provUsers;
|
||||
if ( provUsers == 0 )
|
||||
{
|
||||
if ( oldprovider )
|
||||
provSem.post();
|
||||
}
|
||||
#else
|
||||
int ov = provUsers.fetch_sub( 1, std::memory_order_relaxed );
|
||||
// ov is the previous value, so one means that now it might be 0
|
||||
if ( ov == 1 )
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
ThreadPool::Data::bumpProviderUse ()
|
||||
{
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock lock (provMutex);
|
||||
++provUsers;
|
||||
#else
|
||||
provUsers.fetch_add( 1, std::memory_order_relaxed );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
ThreadPool::Data::setProvider (ThreadPoolProvider *p)
|
||||
{
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
Lock provLock( provMutex );
|
||||
|
||||
if ( oldprovider )
|
||||
throw IEX_INTERNAL_NAMESPACE::ArgExc ("Attempt to set the thread pool provider while"
|
||||
" another thread is currently setting the provider.");
|
||||
|
||||
oldprovider = provider;
|
||||
provider = p;
|
||||
|
||||
while ( provUsers > 0 )
|
||||
{
|
||||
provLock.release();
|
||||
provSem.wait();
|
||||
provLock.acquire();
|
||||
}
|
||||
if ( oldprovider )
|
||||
{
|
||||
oldprovider->finish();
|
||||
delete oldprovider;
|
||||
oldprovider = NULL;
|
||||
}
|
||||
#else
|
||||
ThreadPoolProvider *old = provider.load( std::memory_order_relaxed );
|
||||
do
|
||||
{
|
||||
if ( ! provider.compare_exchange_weak( old, p, std::memory_order_release, std::memory_order_relaxed ) )
|
||||
continue;
|
||||
} while ( false );
|
||||
|
||||
// wait for any other users to finish prior to deleting, given
|
||||
// that these are just mostly to query the thread count or push a
|
||||
// task to the queue (so fast), just spin...
|
||||
//
|
||||
// (well, and normally, people don't do this mid stream anyway, so
|
||||
// this will be 0 99.999% of the time, but just to be safe)
|
||||
//
|
||||
while ( provUsers.load( std::memory_order_relaxed ) > 0 )
|
||||
std::this_thread::yield();
|
||||
|
||||
if ( old )
|
||||
{
|
||||
old->finish();
|
||||
delete old;
|
||||
}
|
||||
|
||||
// NB: the shared_ptr mechanism is safer and means we don't have
|
||||
// to have the provUsers counter since the shared_ptr keeps that
|
||||
// for us. However, gcc 4.8/9 compilers which many people are
|
||||
// still using even though it is 2018 forgot to add the shared_ptr
|
||||
// functions... once that compiler is fully deprecated, switch to
|
||||
// using the below, change provider to a std::shared_ptr and remove
|
||||
// provUsers...
|
||||
//
|
||||
// std::shared_ptr<ThreadPoolProvider> newp( p );
|
||||
// std::shared_ptr<ThreadPoolProvider> curp = std::atomic_load_explicit( &provider, std::memory_order_relaxed );
|
||||
// do
|
||||
// {
|
||||
// if ( ! std::atomic_compare_exchange_weak_explicit( &provider, &curp, newp, std::memory_order_release, std::memory_order_relaxed ) )
|
||||
// continue;
|
||||
// } while ( false );
|
||||
// if ( curp )
|
||||
// curp->finish();
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// class Task
|
||||
//
|
||||
|
||||
Task::Task (TaskGroup* g): _group(g)
|
||||
{
|
||||
if ( g )
|
||||
g->_data->addTask ();
|
||||
}
|
||||
|
||||
|
||||
Task::~Task()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
TaskGroup*
|
||||
Task::group ()
|
||||
{
|
||||
return _group;
|
||||
}
|
||||
|
||||
|
||||
TaskGroup::TaskGroup ():
|
||||
_data (new Data())
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
TaskGroup::~TaskGroup ()
|
||||
{
|
||||
delete _data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TaskGroup::finishOneTask ()
|
||||
{
|
||||
_data->removeTask ();
|
||||
}
|
||||
|
||||
//
|
||||
// class ThreadPoolProvider
|
||||
//
|
||||
|
||||
|
||||
ThreadPoolProvider::ThreadPoolProvider()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ThreadPoolProvider::~ThreadPoolProvider()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// class ThreadPool
|
||||
//
|
||||
|
||||
ThreadPool::ThreadPool (unsigned nthreads):
|
||||
_data (new Data)
|
||||
{
|
||||
if ( nthreads == 0 )
|
||||
_data->setProvider( new NullThreadPoolProvider );
|
||||
else
|
||||
_data->setProvider( new DefaultThreadPoolProvider( int(nthreads) ) );
|
||||
}
|
||||
|
||||
|
||||
ThreadPool::~ThreadPool ()
|
||||
{
|
||||
delete _data;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ThreadPool::numThreads () const
|
||||
{
|
||||
return _data->getProvider ()->numThreads ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ThreadPool::setNumThreads (int count)
|
||||
{
|
||||
if (count < 0)
|
||||
throw IEX_INTERNAL_NAMESPACE::ArgExc ("Attempt to set the number of threads "
|
||||
"in a thread pool to a negative value.");
|
||||
|
||||
bool doReset = false;
|
||||
{
|
||||
Data::SafeProvider sp = _data->getProvider ();
|
||||
int curT = sp->numThreads ();
|
||||
if ( curT == count )
|
||||
return;
|
||||
|
||||
if ( curT == 0 )
|
||||
{
|
||||
NullThreadPoolProvider *npp = dynamic_cast<NullThreadPoolProvider *>( sp.get() );
|
||||
if ( npp )
|
||||
doReset = true;
|
||||
}
|
||||
else if ( count == 0 )
|
||||
{
|
||||
DefaultThreadPoolProvider *dpp = dynamic_cast<DefaultThreadPoolProvider *>( sp.get() );
|
||||
if ( dpp )
|
||||
doReset = true;
|
||||
}
|
||||
if ( ! doReset )
|
||||
sp->setNumThreads( count );
|
||||
}
|
||||
|
||||
if ( doReset )
|
||||
{
|
||||
if ( count == 0 )
|
||||
_data->setProvider( new NullThreadPoolProvider );
|
||||
else
|
||||
_data->setProvider( new DefaultThreadPoolProvider( count ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ThreadPool::setThreadProvider (ThreadPoolProvider *provider)
|
||||
{
|
||||
_data->setProvider (provider);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ThreadPool::addTask (Task* task)
|
||||
{
|
||||
_data->getProvider ()->addTask (task);
|
||||
}
|
||||
|
||||
|
||||
ThreadPool&
|
||||
ThreadPool::globalThreadPool ()
|
||||
{
|
||||
//
|
||||
// The global thread pool
|
||||
//
|
||||
|
||||
static ThreadPool gThreadPool (0);
|
||||
|
||||
return gThreadPool;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ThreadPool::addGlobalTask (Task* task)
|
||||
{
|
||||
globalThreadPool().addTask (task);
|
||||
}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
214
3rdparty/openexr/IlmThread/IlmThreadPool.h
vendored
Normal file
214
3rdparty/openexr/IlmThread/IlmThreadPool.h
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_ILM_THREAD_POOL_H
|
||||
#define INCLUDED_ILM_THREAD_POOL_H
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Task, class ThreadPool, class TaskGroup
|
||||
//
|
||||
// Class ThreadPool manages a set of worker threads and accepts
|
||||
// tasks for processing. Tasks added to the thread pool are
|
||||
// executed concurrently by the worker threads.
|
||||
//
|
||||
// Class Task provides an abstract interface for a task which
|
||||
// a ThreadPool works on. Derived classes need to implement the
|
||||
// execute() function which performs the actual task.
|
||||
//
|
||||
// Class TaskGroup allows synchronization on the completion of a set
|
||||
// of tasks. Every task that is added to a ThreadPool belongs to a
|
||||
// single TaskGroup. The destructor of the TaskGroup waits for all
|
||||
// tasks in the group to finish.
|
||||
//
|
||||
// Note: if you plan to use the ThreadPool interface in your own
|
||||
// applications note that the implementation of the ThreadPool calls
|
||||
// operator delete on tasks as they complete. If you define a custom
|
||||
// operator new for your tasks, for instance to use a custom heap,
|
||||
// then you must also write an appropriate operator delete.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmThreadNamespace.h"
|
||||
#include "IlmThreadExport.h"
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER
|
||||
|
||||
class TaskGroup;
|
||||
class Task;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// ThreadPoolProvider -- this is a pure virtual interface
|
||||
// enabling custom overloading of the threads used and how
|
||||
// the implementation of the processing of tasks
|
||||
// is implemented
|
||||
//-------------------------------------------------------
|
||||
class ILMTHREAD_EXPORT ThreadPoolProvider
|
||||
{
|
||||
public:
|
||||
ThreadPoolProvider();
|
||||
virtual ~ThreadPoolProvider();
|
||||
|
||||
// as in ThreadPool below
|
||||
virtual int numThreads () const = 0;
|
||||
// as in ThreadPool below
|
||||
virtual void setNumThreads (int count) = 0;
|
||||
// as in ThreadPool below
|
||||
virtual void addTask (Task* task) = 0;
|
||||
|
||||
// Ensure that all tasks in this set are finished
|
||||
// and threads shutdown
|
||||
virtual void finish () = 0;
|
||||
|
||||
// Make the provider non-copyable
|
||||
#if __cplusplus >= 201103L
|
||||
ThreadPoolProvider (const ThreadPoolProvider &) = delete;
|
||||
ThreadPoolProvider &operator= (const ThreadPoolProvider &) = delete;
|
||||
ThreadPoolProvider (ThreadPoolProvider &&) = delete;
|
||||
ThreadPoolProvider &operator= (ThreadPoolProvider &&) = delete;
|
||||
#else
|
||||
private:
|
||||
ThreadPoolProvider (const ThreadPoolProvider &);
|
||||
ThreadPoolProvider &operator= (const ThreadPoolProvider &);
|
||||
#endif
|
||||
};
|
||||
|
||||
class ILMTHREAD_EXPORT ThreadPool
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Constructor -- creates numThreads worker threads which
|
||||
// wait until a task is available,
|
||||
// using a default ThreadPoolProvider
|
||||
//-------------------------------------------------------
|
||||
|
||||
ThreadPool (unsigned numThreads = 0);
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Destructor -- waits for all tasks to complete, joins all
|
||||
// the threads to the calling thread, and then destroys them.
|
||||
//-----------------------------------------------------------
|
||||
|
||||
virtual ~ThreadPool ();
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Query and set the number of worker threads in the pool.
|
||||
//
|
||||
// Warning: never call setNumThreads from within a worker
|
||||
// thread as this will almost certainly cause a deadlock
|
||||
// or crash.
|
||||
//--------------------------------------------------------
|
||||
|
||||
int numThreads () const;
|
||||
void setNumThreads (int count);
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Set the thread provider for the pool.
|
||||
//
|
||||
// The ThreadPool takes ownership of the ThreadPoolProvider
|
||||
// and will call delete on it when it is finished or when
|
||||
// it is changed
|
||||
//
|
||||
// Warning: never call setThreadProvider from within a worker
|
||||
// thread as this will almost certainly cause a deadlock
|
||||
// or crash.
|
||||
//--------------------------------------------------------
|
||||
void setThreadProvider (ThreadPoolProvider *provider);
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Add a task for processing. The ThreadPool can handle any
|
||||
// number of tasks regardless of the number of worker threads.
|
||||
// The tasks are first added onto a queue, and are executed
|
||||
// by threads as they become available, in FIFO order.
|
||||
//------------------------------------------------------------
|
||||
|
||||
void addTask (Task* task);
|
||||
|
||||
|
||||
//-------------------------------------------
|
||||
// Access functions for the global threadpool
|
||||
//-------------------------------------------
|
||||
|
||||
static ThreadPool& globalThreadPool ();
|
||||
static void addGlobalTask (Task* task);
|
||||
|
||||
struct Data;
|
||||
|
||||
protected:
|
||||
|
||||
Data * _data;
|
||||
};
|
||||
|
||||
|
||||
class ILMTHREAD_EXPORT Task
|
||||
{
|
||||
public:
|
||||
|
||||
Task (TaskGroup* g);
|
||||
virtual ~Task ();
|
||||
|
||||
virtual void execute () = 0;
|
||||
TaskGroup * group();
|
||||
|
||||
protected:
|
||||
|
||||
TaskGroup * _group;
|
||||
};
|
||||
|
||||
|
||||
class ILMTHREAD_EXPORT TaskGroup
|
||||
{
|
||||
public:
|
||||
|
||||
TaskGroup();
|
||||
~TaskGroup();
|
||||
|
||||
// marks one task as finished
|
||||
// should be used by the thread pool provider to notify
|
||||
// as it finishes tasks
|
||||
void finishOneTask ();
|
||||
|
||||
struct Data;
|
||||
Data* const _data;
|
||||
};
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT
|
||||
|
||||
#endif // INCLUDED_ILM_THREAD_POOL_H
|
||||
100
3rdparty/openexr/IlmThread/IlmThreadPosix.cpp
vendored
Normal file
100
3rdparty/openexr/IlmThread/IlmThreadPosix.cpp
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Thread -- implementation for
|
||||
// platforms that support Posix threads
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#if HAVE_PTHREAD
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
|
||||
#include "IlmThread.h"
|
||||
#include "Iex.h"
|
||||
#include <assert.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
typedef void * (* Start) (void *);
|
||||
}
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
|
||||
bool
|
||||
supportsThreads ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
threadLoop (void * t)
|
||||
{
|
||||
return (reinterpret_cast<Thread*>(t))->run();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Thread::Thread ()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread ()
|
||||
{
|
||||
int error = ::pthread_join (_thread, 0);
|
||||
assert (error == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Thread::start ()
|
||||
{
|
||||
if (int error = ::pthread_create (&_thread, 0, Start (threadLoop), this))
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot create new thread (%T).", error);
|
||||
}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
#endif
|
||||
#endif
|
||||
60
3rdparty/openexr/IlmThread/IlmThreadSemaphore.cpp
vendored
Normal file
60
3rdparty/openexr/IlmThread/IlmThreadSemaphore.cpp
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Semaphore -- dummy implementation for
|
||||
// for platforms that do not support threading
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#if !defined (_WIN32) && !(_WIN64) && !(HAVE_PTHREAD)
|
||||
#include "IlmThreadSemaphore.h"
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
|
||||
Semaphore::Semaphore (unsigned int value) {}
|
||||
Semaphore::~Semaphore () {}
|
||||
void Semaphore::wait () {}
|
||||
bool Semaphore::tryWait () {return true;}
|
||||
void Semaphore::post () {}
|
||||
int Semaphore::value () const {return 0;}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
#endif
|
||||
127
3rdparty/openexr/IlmThread/IlmThreadSemaphore.h
vendored
Normal file
127
3rdparty/openexr/IlmThread/IlmThreadSemaphore.h
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_ILM_THREAD_SEMAPHORE_H
|
||||
#define INCLUDED_ILM_THREAD_SEMAPHORE_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Semaphore -- a wrapper class for
|
||||
// system-dependent counting semaphores
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
#include "IlmThreadExport.h"
|
||||
#include "IlmThreadNamespace.h"
|
||||
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
# ifdef NOMINMAX
|
||||
# undef NOMINMAX
|
||||
# endif
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
#elif HAVE_POSIX_SEMAPHORES
|
||||
# include <semaphore.h>
|
||||
#else
|
||||
# ifdef ILMBASE_FORCE_CXX03
|
||||
# if HAVE_PTHREAD
|
||||
# include <pthread.h>
|
||||
# endif
|
||||
# else
|
||||
# include <mutex>
|
||||
# include <condition_variable>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER
|
||||
|
||||
|
||||
class ILMTHREAD_EXPORT Semaphore
|
||||
{
|
||||
public:
|
||||
|
||||
Semaphore (unsigned int value = 0);
|
||||
virtual ~Semaphore();
|
||||
|
||||
void wait();
|
||||
bool tryWait();
|
||||
void post();
|
||||
int value() const;
|
||||
|
||||
private:
|
||||
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
|
||||
mutable HANDLE _semaphore;
|
||||
|
||||
#elif HAVE_POSIX_SEMAPHORES
|
||||
|
||||
mutable sem_t _semaphore;
|
||||
|
||||
#else
|
||||
//
|
||||
// If the platform has Posix threads but no semapohores,
|
||||
// then we implement them ourselves using condition variables
|
||||
//
|
||||
|
||||
struct sema_t
|
||||
{
|
||||
unsigned int count;
|
||||
unsigned long numWaiting;
|
||||
# if ILMBASE_FORCE_CXX03
|
||||
# if HAVE_PTHREAD
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t nonZero;
|
||||
# else
|
||||
# error unhandled legacy setup
|
||||
# endif
|
||||
# else
|
||||
std::mutex mutex;
|
||||
std::condition_variable nonZero;
|
||||
# endif
|
||||
};
|
||||
|
||||
mutable sema_t _semaphore;
|
||||
|
||||
#endif
|
||||
|
||||
void operator = (const Semaphore& s); // not implemented
|
||||
Semaphore (const Semaphore& s); // not implemented
|
||||
};
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT
|
||||
|
||||
#endif // INCLUDED_ILM_THREAD_SEMAPHORE_H
|
||||
106
3rdparty/openexr/IlmThread/IlmThreadSemaphorePosix.cpp
vendored
Normal file
106
3rdparty/openexr/IlmThread/IlmThreadSemaphorePosix.cpp
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Semaphore -- implementation for platforms
|
||||
// that support Posix threads and Posix semaphores
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#if HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES
|
||||
|
||||
#include "IlmThreadSemaphore.h"
|
||||
#include "Iex.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
|
||||
Semaphore::Semaphore (unsigned int value)
|
||||
{
|
||||
if (::sem_init (&_semaphore, 0, value))
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot initialize semaphore (%T).");
|
||||
}
|
||||
|
||||
|
||||
Semaphore::~Semaphore ()
|
||||
{
|
||||
int error = ::sem_destroy (&_semaphore);
|
||||
assert (error == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::wait ()
|
||||
{
|
||||
while( ::sem_wait( &_semaphore ) == -1 && errno == EINTR )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Semaphore::tryWait ()
|
||||
{
|
||||
return sem_trywait (&_semaphore) == 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::post ()
|
||||
{
|
||||
if (::sem_post (&_semaphore))
|
||||
IEX_NAMESPACE::throwErrnoExc ("Post operation on semaphore failed (%T).");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Semaphore::value () const
|
||||
{
|
||||
int value;
|
||||
|
||||
if (::sem_getvalue (&_semaphore, &value))
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot read semaphore value (%T).");
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
#endif
|
||||
227
3rdparty/openexr/IlmThread/IlmThreadSemaphorePosixCompat.cpp
vendored
Normal file
227
3rdparty/openexr/IlmThread/IlmThreadSemaphorePosixCompat.cpp
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Semaphore -- implementation for for platforms that do
|
||||
// support Posix threads but do not support Posix semaphores,
|
||||
// for example, OS X
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#if (!HAVE_POSIX_SEMAPHORES) && !defined (_WIN32) && ! defined (_WIN64)
|
||||
|
||||
#include "IlmThreadSemaphore.h"
|
||||
#include "Iex.h"
|
||||
#include <assert.h>
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
#if ILMBASE_FORCE_CXX03 && HAVE_PTHREAD
|
||||
Semaphore::Semaphore (unsigned int value)
|
||||
{
|
||||
if (int error = ::pthread_mutex_init (&_semaphore.mutex, 0))
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot initialize mutex (%T).", error);
|
||||
|
||||
if (int error = ::pthread_cond_init (&_semaphore.nonZero, 0))
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot initialize condition variable (%T).",
|
||||
error);
|
||||
|
||||
_semaphore.count = value;
|
||||
_semaphore.numWaiting = 0;
|
||||
}
|
||||
|
||||
|
||||
Semaphore::~Semaphore ()
|
||||
{
|
||||
int error = ::pthread_cond_destroy (&_semaphore.nonZero);
|
||||
assert (error == 0);
|
||||
error = ::pthread_mutex_destroy (&_semaphore.mutex);
|
||||
assert (error == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::wait ()
|
||||
{
|
||||
::pthread_mutex_lock (&_semaphore.mutex);
|
||||
|
||||
_semaphore.numWaiting++;
|
||||
|
||||
while (_semaphore.count == 0)
|
||||
{
|
||||
if (int error = ::pthread_cond_wait (&_semaphore.nonZero,
|
||||
&_semaphore.mutex))
|
||||
{
|
||||
::pthread_mutex_unlock (&_semaphore.mutex);
|
||||
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot wait on condition variable (%T).",
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
_semaphore.numWaiting--;
|
||||
_semaphore.count--;
|
||||
|
||||
::pthread_mutex_unlock (&_semaphore.mutex);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Semaphore::tryWait ()
|
||||
{
|
||||
::pthread_mutex_lock (&_semaphore.mutex);
|
||||
|
||||
if (_semaphore.count == 0)
|
||||
{
|
||||
::pthread_mutex_unlock (&_semaphore.mutex);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_semaphore.count--;
|
||||
::pthread_mutex_unlock (&_semaphore.mutex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::post ()
|
||||
{
|
||||
::pthread_mutex_lock (&_semaphore.mutex);
|
||||
|
||||
if (_semaphore.numWaiting > 0)
|
||||
{
|
||||
int error;
|
||||
if (_semaphore.numWaiting > 1 && _semaphore.count > 1)
|
||||
{
|
||||
error = ::pthread_cond_broadcast (&_semaphore.nonZero);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ::pthread_cond_signal (&_semaphore.nonZero);
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
::pthread_mutex_unlock (&_semaphore.mutex);
|
||||
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot signal condition variable (%T).",
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
_semaphore.count++;
|
||||
::pthread_mutex_unlock (&_semaphore.mutex);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Semaphore::value () const
|
||||
{
|
||||
::pthread_mutex_lock (&_semaphore.mutex);
|
||||
int value = _semaphore.count;
|
||||
::pthread_mutex_unlock (&_semaphore.mutex);
|
||||
return value;
|
||||
}
|
||||
#else
|
||||
Semaphore::Semaphore (unsigned int value)
|
||||
{
|
||||
_semaphore.count = value;
|
||||
_semaphore.numWaiting = 0;
|
||||
}
|
||||
|
||||
|
||||
Semaphore::~Semaphore ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::wait ()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(_semaphore.mutex);
|
||||
|
||||
_semaphore.numWaiting++;
|
||||
|
||||
while (_semaphore.count == 0)
|
||||
_semaphore.nonZero.wait (lk);
|
||||
|
||||
_semaphore.numWaiting--;
|
||||
_semaphore.count--;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Semaphore::tryWait ()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(_semaphore.mutex);
|
||||
|
||||
if (_semaphore.count == 0)
|
||||
return false;
|
||||
|
||||
_semaphore.count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::post ()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(_semaphore.mutex);
|
||||
|
||||
_semaphore.count++;
|
||||
if (_semaphore.numWaiting > 0)
|
||||
{
|
||||
if (_semaphore.count > 1)
|
||||
_semaphore.nonZero.notify_all();
|
||||
else
|
||||
_semaphore.nonZero.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Semaphore::value () const
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(_semaphore.mutex);
|
||||
return _semaphore.count;
|
||||
}
|
||||
#endif
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
#endif
|
||||
147
3rdparty/openexr/IlmThread/IlmThreadSemaphoreWin32.cpp
vendored
Normal file
147
3rdparty/openexr/IlmThread/IlmThreadSemaphoreWin32.cpp
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Semaphore -- implementation for Windows
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "IlmThreadSemaphore.h"
|
||||
#include "Iex.h"
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
using namespace IEX_NAMESPACE;
|
||||
|
||||
namespace {
|
||||
|
||||
std::string
|
||||
errorString ()
|
||||
{
|
||||
LPSTR messageBuffer;
|
||||
DWORD bufferLength;
|
||||
std::string message;
|
||||
|
||||
//
|
||||
// Call FormatMessage() to allow for message
|
||||
// text to be acquired from the system.
|
||||
//
|
||||
|
||||
if (bufferLength = FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
0,
|
||||
GetLastError (),
|
||||
MAKELANGID (LANG_NEUTRAL,
|
||||
SUBLANG_DEFAULT),
|
||||
(LPSTR) &messageBuffer,
|
||||
0,
|
||||
NULL))
|
||||
{
|
||||
message = messageBuffer;
|
||||
LocalFree (messageBuffer);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Semaphore::Semaphore (unsigned int value)
|
||||
{
|
||||
if ((_semaphore = ::CreateSemaphore (0, value, 0x7fffffff, 0)) == 0)
|
||||
{
|
||||
THROW (LogicExc, "Could not create semaphore "
|
||||
"(" << errorString() << ").");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
bool ok = ::CloseHandle (_semaphore) != FALSE;
|
||||
assert (ok);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::wait()
|
||||
{
|
||||
if (::WaitForSingleObject (_semaphore, INFINITE) != WAIT_OBJECT_0)
|
||||
{
|
||||
THROW (LogicExc, "Could not wait on semaphore "
|
||||
"(" << errorString() << ").");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Semaphore::tryWait()
|
||||
{
|
||||
return ::WaitForSingleObject (_semaphore, 0) == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Semaphore::post()
|
||||
{
|
||||
if (!::ReleaseSemaphore (_semaphore, 1, 0))
|
||||
{
|
||||
THROW (LogicExc, "Could not post on semaphore "
|
||||
"(" << errorString() << ").");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Semaphore::value() const
|
||||
{
|
||||
LONG v = -1;
|
||||
|
||||
if (!::ReleaseSemaphore (_semaphore, 0, &v) || v < 0)
|
||||
{
|
||||
THROW (LogicExc, "Could not get value of semaphore "
|
||||
"(" << errorString () << ").");
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
101
3rdparty/openexr/IlmThread/IlmThreadWin32.cpp
vendored
Normal file
101
3rdparty/openexr/IlmThread/IlmThreadWin32.cpp
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas
|
||||
// Digital Ltd. LLC
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Industrial Light & Magic nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// class Thread -- implementation for Windows
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "IlmBaseConfig.h"
|
||||
|
||||
#ifdef ILMBASE_FORCE_CXX03
|
||||
|
||||
#include "IlmThread.h"
|
||||
#include "Iex.h"
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
|
||||
bool
|
||||
supportsThreads ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
unsigned __stdcall
|
||||
threadLoop (void * t)
|
||||
{
|
||||
reinterpret_cast<Thread*>(t)->run();
|
||||
_endthreadex (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Thread::Thread ()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread ()
|
||||
{
|
||||
DWORD status = ::WaitForSingleObject (_thread, INFINITE);
|
||||
assert (status == WAIT_OBJECT_0);
|
||||
bool ok = ::CloseHandle (_thread) != FALSE;
|
||||
assert (ok);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Thread::start ()
|
||||
{
|
||||
unsigned id;
|
||||
_thread = (HANDLE)::_beginthreadex (0, 0, &threadLoop, this, 0, &id);
|
||||
|
||||
if (_thread == 0)
|
||||
IEX_NAMESPACE::throwErrnoExc ("Cannot create new thread (%T).");
|
||||
}
|
||||
|
||||
|
||||
ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user