From 77d267d2031d5f0ac4087cda69cd082729a6e75f Mon Sep 17 00:00:00 2001 From: Christoph Lipka Date: Tue, 12 Feb 2019 03:51:26 +0100 Subject: [PATCH] More miscellaneous code cleanup / modernization. - Change include hierarchy, using more dedicated forward declaration headers. - Make use of C++11 standard library for threads and timing. - Start work on tearing down `TraceThreadData`. - Some odds and ends. --- .travis.yml | 1 - changes.txt | 3 +- platform/unix/syspovtimer.cpp | 73 ++++++-- platform/unix/syspovtimer.h | 28 ++- platform/windows/syspovtimer.cpp | 13 ++ platform/windows/syspovtimer.h | 4 +- platform/x86/avx/avxnoise.cpp | 4 +- platform/x86/avx2fma3/avx2fma3noise.cpp | 2 +- source-doc/styleguide.md | 3 +- source/backend/bounding/boundingtask.cpp | 1 - source/backend/configbackend.h | 38 ---- source/backend/control/messagefactory.cpp | 4 - source/backend/control/parsertask.cpp | 3 +- source/backend/control/parsertask.h | 1 - source/backend/control/scene.cpp | 14 +- source/backend/control/scene.h | 8 +- .../lighting/photonshootingstrategy.cpp | 2 +- .../backend/lighting/photonshootingstrategy.h | 6 +- .../backend/lighting/photonshootingtask.cpp | 1 + source/backend/povray.cpp | 18 +- source/backend/povray.h | 8 +- source/backend/precomp.h | 13 +- source/backend/render/radiositytask.cpp | 6 +- source/backend/render/rendertask.cpp | 1 - source/backend/render/tracetask.cpp | 4 +- source/backend/scene/backendscenedata.cpp | 4 - source/backend/scene/view.cpp | 38 ++-- source/backend/scene/view.h | 16 +- source/backend/support/task.cpp | 20 ++- source/backend/support/task.h | 39 +--- source/backend/support/taskqueue.cpp | 27 ++- source/backend/support/taskqueue.h | 9 +- source/base/base_fwd.h | 8 + source/base/configbase.h | 70 +++----- source/base/filesystem_fwd.h | 9 +- source/base/image/colourspace.cpp | 14 +- source/base/image/colourspace.h | 12 +- source/base/image/colourspace_fwd.h | 9 +- source/base/image/dither_fwd.h | 9 +- source/base/image/metadata.h | 1 - source/base/image/tiff.cpp | 3 - source/base/pov_mem.cpp | 6 +- source/base/pov_mem.h | 1 + source/base/precomp.h | 13 +- source/base/stringutilities.h | 6 +- source/base/timer.cpp | 44 ++--- source/base/timer.h | 108 +++++++---- source/core/bounding/boundingbox.cpp | 4 +- source/core/configcore.h | 2 +- source/core/core_fwd.h | 3 + source/core/coretypes.h | 2 - source/core/lighting/photons.cpp | 2 + source/core/lighting/radiosity.cpp | 19 +- source/core/lighting/radiosity.h | 14 +- source/core/material/media.cpp | 2 + source/core/material/noise.cpp | 4 +- source/core/material/noise.h | 4 +- source/core/material/normal.cpp | 1 + source/core/material/pattern.cpp | 60 +++---- source/core/material/pattern.h | 75 -------- source/core/material/pattern_fwd.h | 3 +- source/core/math/jitter.h | 2 +- source/core/math/randomsequence.cpp | 14 +- source/core/math/randomsequence.h | 1 + source/core/math/randomsequence_fwd.h | 74 ++++++++ source/core/math/vector.h | 1 + source/core/math/vector_fwd.h | 60 +++++++ source/core/precomp.h | 12 +- source/core/render/trace.cpp | 4 +- source/core/render/tracepixel.cpp | 6 +- source/core/scene/object.cpp | 1 + source/core/scene/scenedata.cpp | 3 - source/core/scene/scenedata.h | 1 + source/core/scene/scenedata_fwd.h | 51 ++++++ source/core/scene/tracethreaddata.cpp | 49 +---- source/core/scene/tracethreaddata.h | 22 +-- source/core/shape/bezier.cpp | 6 +- source/core/shape/blob.cpp | 10 +- source/core/shape/box.cpp | 1 + source/core/shape/cone.cpp | 1 + source/core/shape/csg.cpp | 1 + source/core/shape/disc.cpp | 1 + source/core/shape/fractal.cpp | 1 + source/core/shape/heightfield.cpp | 1 + source/core/shape/isosurface.cpp | 1 + source/core/shape/lathe.cpp | 1 + source/core/shape/lemon.cpp | 1 + source/core/shape/mesh.cpp | 23 +-- source/core/shape/mesh.h | 15 +- source/core/shape/ovus.cpp | 1 + source/core/shape/parametric.cpp | 1 + source/core/shape/plane.cpp | 1 + source/core/shape/polygon.cpp | 1 + source/core/shape/polynomial.cpp | 1 + source/core/shape/prism.cpp | 1 + source/core/shape/quadric.cpp | 1 + source/core/shape/sor.cpp | 1 + source/core/shape/sphere.cpp | 1 + source/core/shape/spheresweep.cpp | 1 + source/core/shape/superellipsoid.cpp | 1 + source/core/shape/torus.cpp | 1 + source/core/shape/triangle.cpp | 1 + source/core/shape/truetype.cpp | 1 + source/core/support/cracklecache.cpp | 151 ++++++++++++++++ source/core/support/cracklecache.h | 169 ++++++++++++++++++ source/core/support/cracklecache_fwd.h | 55 ++++++ source/core/support/octree.cpp | 9 +- source/core/support/octree_fwd.h | 9 +- source/core/support/statistics.h | 1 + source/core/support/statistics_fwd.h | 51 ++++++ source/frontend/imagemessagehandler.cpp | 1 - source/frontend/parsermessagehandler.cpp | 1 + source/frontend/precomp.h | 10 -- source/frontend/processrenderoptions.cpp | 1 - source/frontend/renderfrontend.cpp | 2 +- source/frontend/renderfrontend.h | 3 + source/frontend/rendermessagehandler.cpp | 4 +- source/frontend/shelloutprocessing.cpp | 1 - source/frontend/simplefrontend.h | 3 + source/parser/fncode.cpp | 2 +- source/parser/parser.cpp | 17 +- source/parser/parser.h | 3 + source/parser/parser_expressions.cpp | 13 +- source/parser/parser_strings.cpp | 5 +- source/parser/parsertypes.cpp | 2 - source/parser/parsertypes.h | 3 - source/parser/precomp.h | 13 +- source/parser/rawtokenizer.cpp | 2 - source/parser/rawtokenizer.h | 3 - source/parser/scanner.cpp | 3 - source/parser/scanner.h | 3 - source/parser/symboltable.cpp | 5 +- source/parser/symboltable.h | 3 - source/povmain.cpp | 1 - source/povms/precomp.h | 12 -- source/vm/fnintern.cpp | 1 + source/vm/fnpovfpu.cpp | 1 + source/vm/precomp.h | 11 -- tests/source/tests.h | 4 +- tools/doxygen/doxygen.cfg | 4 +- tools/doxygen/source-doc.cfg | 3 +- unix/README.md | 1 - unix/configure.ac | 39 ---- unix/disp_sdl.cpp | 2 + unix/install.txt | 6 - unix/povconfig/syspovconfig_gnu.h | 1 - unix/povconfig/syspovconfigbackend.h | 8 +- unix/povconfig/syspovconfigbase.h | 18 +- vfe/unix/unixconsole.cpp | 50 ++++-- vfe/unix/vfeplatform.cpp | 3 + vfe/unix/vfeplatform.h | 2 - vfe/vfe.cpp | 3 + vfe/vfe.h | 4 - vfe/vfepovms.cpp | 19 +- vfe/vfeprecomp.h | 153 ++++++++-------- vfe/vfesession.cpp | 76 ++++---- vfe/vfesession.h | 28 +-- windows/povconfig/syspovconfig.h | 18 +- windows/povconfig/syspovconfig_msvc.h | 2 - windows/povconfig/syspovconfigbase.h | 3 +- windows/pvdisplay.cpp | 9 +- windows/pvengine.cpp | 13 +- windows/pvengine.h | 106 +---------- windows/pvmem.cpp | 6 +- windows/pvmem.h | 15 +- windows/pvtext.cpp | 4 +- windows/vs2015/console.vcxproj | 9 - windows/vs2015/povcore.vcxproj | 7 + windows/vs2015/povcore.vcxproj.filters | 21 +++ windows/vs2015/povray.sln | 6 - windows/vs2015/povray.vcxproj | 6 - windows/winprecomp.h | 11 +- 172 files changed, 1433 insertions(+), 1099 deletions(-) create mode 100644 source/core/math/randomsequence_fwd.h create mode 100644 source/core/math/vector_fwd.h create mode 100644 source/core/scene/scenedata_fwd.h create mode 100644 source/core/support/cracklecache.cpp create mode 100644 source/core/support/cracklecache.h create mode 100644 source/core/support/cracklecache_fwd.h create mode 100644 source/core/support/statistics_fwd.h diff --git a/.travis.yml b/.travis.yml index 46701f4f2..cb2a719fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,6 @@ addons: packages: - libboost-dev - libboost-date-time-dev - - libboost-thread-dev - libjpeg8-dev - libopenexr-dev - libpng12-dev diff --git a/changes.txt b/changes.txt index 990b1da88..0c4fc70b8 100644 --- a/changes.txt +++ b/changes.txt @@ -155,7 +155,7 @@ Reported by Coverity static code analysis: Miscellaneous: - - Fix `interior_texture` for text objects (as mentioned in GitHub issue #65) + - Fix `interior_texture` for text objects (as mentioned in GitHub issue #65). - Eliminated use of deprecated C++ `register` keyword (except in 3rd party libraries bundled with the POV-Ray source code). - Fix long-standing bug in Julia fractal primitive using hypercomplex numbers. @@ -195,6 +195,7 @@ Other Noteworthy - The `./configure` script can now be run without the `COMPILED_BY=...` option. In this case it defaults to `$USER `, where `$USER` is your login name. + - The `boost_thread` and `boost_system` libraries are no longer required. Changes between 3.7.1-beta.9 and 3.7.1-rc.1 diff --git a/platform/unix/syspovtimer.cpp b/platform/unix/syspovtimer.cpp index 239a59316..226f3518b 100644 --- a/platform/unix/syspovtimer.cpp +++ b/platform/unix/syspovtimer.cpp @@ -36,6 +36,7 @@ #include "syspovtimer.h" +#include #include #ifdef HAVE_UNISTD_H @@ -69,24 +70,47 @@ namespace pov_base //****************************************************************************** -#if !POV_USE_DEFAULT_DELAY +#if (POV_USE_PLATFORM_DELAY == 1) +// NOTE: Even if we decide to discontinue the use of this implementation, +// we may want to keep it around in case it may turn out to be superior on some +// exotic systems. void Delay(unsigned int msec) { -#if defined(HAVE_NANOSLEEP) - timespec ts; + timespec ts, remain; ts.tv_sec = msec / 1000; ts.tv_nsec = (POV_ULONG) (1000000) * (msec % 1000); - nanosleep(&ts, nullptr); -#elif defined(HAVE_USLEEP) - POV_ASSERT(msec < 1000); // On some systems, usleep() does not support sleeping for 1 second or more. - usleep (msec * (useconds_t)1000); -#else -#error "Bad compile-time configuration." -#endif + errno = 0; + while ((nanosleep(&ts, &remain) != 0) && (errno == EINTR)) + { + ts = remain; + errno = 0; + } +} + +#elif (POV_USE_PLATFORM_DELAY == 2) + +// ATTENTION: According to the POSIX standard, `usleep()` need not be +// thread-safe! + +// NOTE: Although we're currently not using this implementation, we may want to +// keep it around in case we find the default implementation wanting on some +// systems. +void Delay(unsigned int msec) +{ + // According to the POSIX standard, `usleep()` may not support parameter + // values of 1 million or higher (corresponding to 1s). We work around this + // by simply calling `usleep()` repeatedly until we're good. + for (unsigned int sec = 0; sec < (msec/1000); ++sec) + usleep((useconds_t)999999); // not exactly 1s, but close enough. + usleep ((msec % 1000) * (useconds_t)1000); } -#endif // !POV_USE_DEFAULT_DELAY +#else // POV_USE_PLATFORM_DELAY + +#error "Bad compile-time configuration." + +#endif // POV_USE_PLATFORM_DELAY //****************************************************************************** @@ -138,9 +162,11 @@ static inline bool GettimeofdayMillisec(POV_ULONG& result) } Timer::Timer () : +#if !POVUNIX_USE_DEFAULT_REAL_TIMER mWallTimeUseClockGettimeMonotonic (false), mWallTimeUseClockGettimeRealtime (false), mWallTimeUseGettimeofday (false), +#endif mProcessTimeUseGetrusageSelf (false), mProcessTimeUseClockGettimeProcess (false), mProcessTimeUseFallback (false), @@ -149,6 +175,7 @@ Timer::Timer () : mThreadTimeUseClockGettimeThread (false), mThreadTimeUseFallback (false) { +#if !POVUNIX_USE_DEFAULT_REAL_TIMER // Figure out which timer source to use for wall clock time. bool haveWallTime = false; #if defined(HAVE_DECL_CLOCK_MONOTONIC) && HAVE_DECL_CLOCK_MONOTONIC @@ -165,12 +192,13 @@ Timer::Timer () : // gettimeofday(), and document it here. if (!haveWallTime) haveWallTime = mWallTimeUseGettimeofday = GettimeofdayMillisec(mWallTimeStart); - // FIXME: add fallback, using ftime(), or time() + a counter for ms, or maybe boost::date_time + // FIXME: add fallback, using ftime(), or time() + a counter for ms, or maybe std::chrono if (!haveWallTime) { POV_ASSERT(false); mWallTimeStart = 0; } +#endif // Figure out which timer source to use for per-process CPU time. bool haveProcessTime = false; @@ -186,8 +214,12 @@ Timer::Timer () : #endif if (!haveProcessTime) { +#if POVUNIX_USE_DEFAULT_REAL_TIMER + haveProcessTime = mProcessTimeUseFallback = true; +#else haveProcessTime = mProcessTimeUseFallback = haveWallTime; mProcessTimeStart = mWallTimeStart; +#endif } // Figure out which timer source to use for per-thread CPU time. @@ -212,11 +244,7 @@ Timer::Timer () : } } -Timer::~Timer () -{ - // nothing to do -} - +#if !POVUNIX_USE_DEFAULT_REAL_TIMER POV_ULONG Timer::GetWallTime () const { POV_ULONG result; @@ -232,6 +260,7 @@ POV_ULONG Timer::GetWallTime () const return (GettimeofdayMillisec(result) ? result : 0); return 0; } +#endif POV_ULONG Timer::GetProcessTime () const { @@ -245,7 +274,11 @@ POV_ULONG Timer::GetProcessTime () const return (ClockGettimeMillisec(result, CLOCK_PROCESS_CPUTIME_ID) ? result : 0); #endif if (mProcessTimeUseFallback) +#if POVUNIX_USE_DEFAULT_REAL_TIMER + return mRealTimer.ElapsedTime(); +#else return GetWallTime (); +#endif return 0; } @@ -269,10 +302,12 @@ POV_ULONG Timer::GetThreadTime () const return 0; } +#if !POVUNIX_USE_DEFAULT_REAL_TIMER POV_LONG Timer::ElapsedRealTime () const { return GetWallTime () - mWallTimeStart; } +#endif POV_LONG Timer::ElapsedProcessCPUTime () const { @@ -286,7 +321,11 @@ POV_LONG Timer::ElapsedThreadCPUTime () const void Timer::Reset () { +#if POVUNIX_USE_DEFAULT_REAL_TIMER + mRealTimer.Reset(); +#else mWallTimeStart = GetWallTime (); +#endif mProcessTimeStart = GetProcessTime (); mThreadTimeStart = GetThreadTime (); } diff --git a/platform/unix/syspovtimer.h b/platform/unix/syspovtimer.h index b70305ff4..9983ce405 100644 --- a/platform/unix/syspovtimer.h +++ b/platform/unix/syspovtimer.h @@ -39,17 +39,19 @@ #include "base/configbase.h" +#include "base/timer.h" + namespace pov_base { -#if !POV_USE_DEFAULT_DELAY - -void Delay(unsigned int msec); - -#endif // !POV_USE_DEFAULT_DELAY +#if !POV_USE_DEFAULT_TIMER +// NOTE: Although we're currently not using platform-specific implementations +// of the wall clock timer, we may want to keep them around in case we find the +// default implementation wanting on particular flavours of Unix. +#define POVUNIX_USE_DEFAULT_REAL_TIMER 1 -#if !POV_USE_DEFAULT_TIMER +class DefaultRealTimer; /// Millisecond-precision timer. /// @@ -67,9 +69,13 @@ class Timer final public: Timer(); - ~Timer(); + ~Timer() = default; +#if POVUNIX_USE_DEFAULT_REAL_TIMER + inline POV_LONG ElapsedRealTime() const { return mRealTimer.ElapsedTime(); } +#else POV_LONG ElapsedRealTime() const; +#endif POV_LONG ElapsedProcessCPUTime() const; POV_LONG ElapsedThreadCPUTime() const; @@ -80,13 +86,19 @@ class Timer final private: +#if POVUNIX_USE_DEFAULT_REAL_TIMER + DefaultRealTimer mRealTimer; +#else POV_ULONG mWallTimeStart; +#endif POV_ULONG mProcessTimeStart; POV_ULONG mThreadTimeStart; +#if !POVUNIX_USE_DEFAULT_REAL_TIMER bool mWallTimeUseClockGettimeMonotonic : 1; ///< Whether we'll measure elapsed wall-clock time using `clock_gettime(CLOCK_MONOTONIC)`. bool mWallTimeUseClockGettimeRealtime : 1; ///< Whether we'll measure elapsed wall-clock time using `clock_gettime(CLOCK_REALTIME)`. bool mWallTimeUseGettimeofday : 1; ///< Whether we'll measure elapsed wall-clock time using `gettimeofday()`. +#endif bool mProcessTimeUseGetrusageSelf : 1; ///< Whether we'll measure per-process CPU time using `getrusage(RUSAGE_SELF)`. bool mProcessTimeUseClockGettimeProcess : 1; ///< Whether we'll measure per-process CPU time using `clock_gettime(CLOCK_PROCESS_CPUTIME_ID)`. @@ -97,7 +109,9 @@ class Timer final bool mThreadTimeUseClockGettimeThread : 1; ///< Whether we'll measure per-thread CPU time `clock_gettime(CLOCK_THREAD_CPUTIME_ID)`. bool mThreadTimeUseFallback : 1; ///< Whether we'll fall back to per-process CPU time (or wall-clock time) instead of per-thread CPU time. +#if !POVUNIX_USE_DEFAULT_REAL_TIMER POV_ULONG GetWallTime() const; +#endif POV_ULONG GetThreadTime() const; POV_ULONG GetProcessTime() const; }; diff --git a/platform/windows/syspovtimer.cpp b/platform/windows/syspovtimer.cpp index e4b793eb0..a00f7f482 100644 --- a/platform/windows/syspovtimer.cpp +++ b/platform/windows/syspovtimer.cpp @@ -53,13 +53,22 @@ namespace pov_base //****************************************************************************** +#if POV_USE_PLATFORM_DELAY + +// NOTE: Although we're currently not using this implementation, we may want to +// keep it around in case we find the default implementation wanting on Windows +// systems in general or some flavours in particular. void Delay(unsigned int msec) { Sleep (msec); } +#endif // POV_USE_PLATFORM_DELAY + //****************************************************************************** +#if !POV_USE_DEFAULT_TIMER + Timer::Timer () : // TODO - sources on the internet indicate that GetThreadTimes() and GetProcessTimes() have been // around as early as NT 3.1. Is there a reason we're only making use of it in NT 4.0 and @@ -175,5 +184,9 @@ bool Timer::HasValidProcessCPUTime () const return mCPUTimeSupported; } +#endif // POV_USE_DEFAULT_TIMER + +//****************************************************************************** + } // end of namespace pov_base diff --git a/platform/windows/syspovtimer.h b/platform/windows/syspovtimer.h index d6610fdd4..d43986549 100644 --- a/platform/windows/syspovtimer.h +++ b/platform/windows/syspovtimer.h @@ -42,7 +42,7 @@ namespace pov_base { -void Delay(unsigned int msec); +#if !POV_USE_DEFAULT_TIMER class Timer final { @@ -72,6 +72,8 @@ class Timer final POV_ULONG GetProcessTime () const; }; +#endif // POV_USE_DEFAULT_TIMER + } // end of namespace pov_base diff --git a/platform/x86/avx/avxnoise.cpp b/platform/x86/avx/avxnoise.cpp index 047b28bfb..1bd6da533 100644 --- a/platform/x86/avx/avxnoise.cpp +++ b/platform/x86/avx/avxnoise.cpp @@ -79,7 +79,7 @@ static inline __m256d permute4x64_functional(const __m256d& x, int i) const int idx1 = ((i >> 2) & 0x3); const int idx2 = ((i >> 4) & 0x3); const int idx3 = ((i >> 6) & 0x3); - ALIGN32 double p[4]; + alignas(32) double p[4]; _mm256_store_pd(p,x); if (idx0 == idx1 && idx1 == idx2 && idx2 == idx3) @@ -134,7 +134,7 @@ static inline __m256d permute4x64_functional(const __m256d& x, int i) extern DBL RTable[]; -ALIGN32 static AVXTABLETYPE AVXRTable[267]; +alignas(32) static AVXTABLETYPE AVXRTable[267]; void AVXNoiseInit() { diff --git a/platform/x86/avx2fma3/avx2fma3noise.cpp b/platform/x86/avx2fma3/avx2fma3noise.cpp index ba4b5827d..616527956 100644 --- a/platform/x86/avx2fma3/avx2fma3noise.cpp +++ b/platform/x86/avx2fma3/avx2fma3noise.cpp @@ -121,7 +121,7 @@ const bool kAVX2FMA3NoiseEnabled = true; extern DBL RTable[]; -ALIGN32 static AVX2TABLETYPE AVX2RTable[267]; +alignas(32) static AVX2TABLETYPE AVX2RTable[267]; void AVX2FMA3NoiseInit() { diff --git a/source-doc/styleguide.md b/source-doc/styleguide.md index 80763460b..cef442af6 100644 --- a/source-doc/styleguide.md +++ b/source-doc/styleguide.md @@ -53,7 +53,6 @@ POV-Ray is being developed with portability high in mind. In practice and at pre - While POV-Ray does require boost, we want to keep dependency on it to a minimum. The following are currently considered fair game: - Flyweights. - - Threads. - DateTime **except** features that may require linking with the lib (mostly conversions to/from string). - SmartPtr intrusive pointers. . @@ -171,6 +170,8 @@ Parameter and variable names might carry one or more additional prefixes. These . - Protected or private member variable names should begin with a (possibly additional) `m` prefix. - Global variable names should begin with a (possibly additional) `g` prefix. + - Global variables with thread-local storage should begin with a (possibly additional) `gt` + - prefix. - Constants should begin with a `k` prefix. (Does not apply to const parameters.) . diff --git a/source/backend/bounding/boundingtask.cpp b/source/backend/bounding/boundingtask.cpp index f05ae93bd..f49e9b821 100644 --- a/source/backend/bounding/boundingtask.cpp +++ b/source/backend/bounding/boundingtask.cpp @@ -45,7 +45,6 @@ // Boost header files #include -#include // POV-Ray header files (base module) // (none at the moment) diff --git a/source/backend/configbackend.h b/source/backend/configbackend.h index 1a2c63212..cbed8b408 100644 --- a/source/backend/configbackend.h +++ b/source/backend/configbackend.h @@ -77,35 +77,6 @@ #define POV_USE_DEFAULT_TASK_CLEANUP 1 #endif -/// @def POV_THREAD_STACK_SIZE -/// Default thread stack size. -/// -#ifndef POV_THREAD_STACK_SIZE - #define POV_THREAD_STACK_SIZE (2 * 1024 * 1024) // 2 MiB -#endif - -static_assert( - POV_THREAD_STACK_SIZE >= 1024 * 1024, - "Unreasonably small thread stack size. Proceed at your own risk." -); - -/// @def POV_CONVERT_TEXT_TO_UCS2 -/// Convert text from system-specific format to UCS2. -/// -/// @note -/// The macro is responsible for creating a sufficiently large result buffer, using @ref POV_MALLOC(). -/// @note -/// The result must be a genuine UCS2 string. UCS4/Unicode characters outside the Basic Multilingual Plane -/// are not supported. -/// -/// @param[in] ts Null-terminated byte sequence to convert. -/// @param[out] as Number of UCS2 characters in result. -/// @return Converted null-terminated UCS2 character sequence, or `nullptr` if conversion is not supported. -/// -#ifndef POV_CONVERT_TEXT_TO_UCS2 - #define POV_CONVERT_TEXT_TO_UCS2(ts, as) (nullptr) -#endif - //****************************************************************************** /// /// @name Debug Settings. @@ -165,15 +136,6 @@ static_assert( #define POV_TASK_ASSERT(expr) POV_ASSERT_DISABLE(expr) #endif -/// @def HAVE_BOOST_THREAD_ATTRIBUTES -/// Whether boost::thread::attributes is available (and can be used to set a thread's stack size). -/// -#if BOOST_VERSION >= 105000 - #define HAVE_BOOST_THREAD_ATTRIBUTES 1 -#else - #define HAVE_BOOST_THREAD_ATTRIBUTES 0 -#endif - /// @} /// //****************************************************************************** diff --git a/source/backend/control/messagefactory.cpp b/source/backend/control/messagefactory.cpp index 48c8bc6b1..adde3762d 100644 --- a/source/backend/control/messagefactory.cpp +++ b/source/backend/control/messagefactory.cpp @@ -40,10 +40,6 @@ // C++ standard header files // (none at the moment) -// Boost header files -#include -#include - // POV-Ray header files (base module) #include "base/povassert.h" diff --git a/source/backend/control/parsertask.cpp b/source/backend/control/parsertask.cpp index a07d44946..52157a320 100644 --- a/source/backend/control/parsertask.cpp +++ b/source/backend/control/parsertask.cpp @@ -38,8 +38,9 @@ // C++ variants of C standard header files // C++ standard header files + // Boost header files -// (none at the moment) +#include // POV-Ray header files (base module) #include "base/types.h" diff --git a/source/backend/control/parsertask.h b/source/backend/control/parsertask.h index bc8d786d0..75a6cdc9a 100644 --- a/source/backend/control/parsertask.h +++ b/source/backend/control/parsertask.h @@ -45,7 +45,6 @@ // C++ standard header files #include -// Boost header files // POV-Ray header files (base module) // POV-Ray header files (core module) // (none at the moment) diff --git a/source/backend/control/scene.cpp b/source/backend/control/scene.cpp index f4dc518b9..c8376f9c4 100644 --- a/source/backend/control/scene.cpp +++ b/source/backend/control/scene.cpp @@ -42,9 +42,9 @@ // C++ standard header files #include #include +#include // Boost header files -#include #include // POV-Ray header files (base module) @@ -106,7 +106,7 @@ void Scene::StartParser(POVMS_Object& parseOptions) // A scene can only be parsed once if (parserControlThread == nullptr) - parserControlThread = Task::NewBoostThread(boost::bind(&Scene::ParserControlThread, this), POV_THREAD_STACK_SIZE); + parserControlThread = new std::thread(boost::bind(&Scene::ParserControlThread, this)); else return; @@ -274,7 +274,10 @@ void Scene::GetStatistics(POVMS_Object& parserStats) for(std::vector::iterator i(sceneThreadData.begin()); i != sceneThreadData.end(); i++) { timeData[(*i)->timeType].realTime = max(timeData[(*i)->timeType].realTime, (*i)->realTime); - timeData[(*i)->timeType].cpuTime += (*i)->cpuTime; + if ((*i)->cpuTime >= 0) + timeData[(*i)->timeType].cpuTime += (*i)->cpuTime; + else + timeData[(*i)->timeType].cpuTime = -1; timeData[(*i)->timeType].samples++; } @@ -285,7 +288,8 @@ void Scene::GetStatistics(POVMS_Object& parserStats) POVMS_Object elapsedTime(kPOVObjectClass_ElapsedTime); elapsedTime.SetLong(kPOVAttrib_RealTime, timeData[i].realTime); - elapsedTime.SetLong(kPOVAttrib_CPUTime, timeData[i].cpuTime); + if (timeData[i].cpuTime >= 0) + elapsedTime.SetLong(kPOVAttrib_CPUTime, timeData[i].cpuTime); elapsedTime.SetInt(kPOVAttrib_TimeSamples, POVMSInt(timeData[i].samples)); switch(i) @@ -369,7 +373,7 @@ void Scene::ParserControlThread() if(stopRequsted == false) { - boost::thread::yield(); + std::this_thread::yield(); Delay(10); } } diff --git a/source/backend/control/scene.h b/source/backend/control/scene.h index f5c5f7826..6288c2c3a 100644 --- a/source/backend/control/scene.h +++ b/source/backend/control/scene.h @@ -45,13 +45,11 @@ // C++ standard header files #include +// not required for `std::thread` because we forward-declare it in `base/base_fwd.h` #include -// Boost header files -#include - // POV-Ray header files (base module) -// (none at the moment) +#include "base/base_fwd.h" // POV-Ray header files (core module) #include "core/core_fwd.h" @@ -190,7 +188,7 @@ class Scene final /// stop request flag bool stopRequsted; /// parser control thread - boost::thread *parserControlThread; + std::thread *parserControlThread; /** * Send the parser statistics upon completion of a parsing. diff --git a/source/backend/lighting/photonshootingstrategy.cpp b/source/backend/lighting/photonshootingstrategy.cpp index 3c808c241..3db547533 100644 --- a/source/backend/lighting/photonshootingstrategy.cpp +++ b/source/backend/lighting/photonshootingstrategy.cpp @@ -75,7 +75,7 @@ void PhotonShootingStrategy::start() PhotonShootingUnit* PhotonShootingStrategy::getNextUnit() { - boost::mutex::scoped_lock lock(nextUnitMutex); + std::lock_guard lock(nextUnitMutex); if (iter == units.end()) return nullptr; PhotonShootingUnit* unit = *iter; diff --git a/source/backend/lighting/photonshootingstrategy.h b/source/backend/lighting/photonshootingstrategy.h index 6774b979a..6f7c5ddd9 100644 --- a/source/backend/lighting/photonshootingstrategy.h +++ b/source/backend/lighting/photonshootingstrategy.h @@ -45,11 +45,9 @@ // C++ standard header files #include +#include #include -// Boost header files -#include - // POV-Ray header files (base module) // (none at the moment) @@ -78,7 +76,7 @@ class PhotonShootingStrategy final private: std::vector::iterator iter; - boost::mutex nextUnitMutex; + std::mutex nextUnitMutex; }; diff --git a/source/backend/lighting/photonshootingtask.cpp b/source/backend/lighting/photonshootingtask.cpp index ce593ebb0..860943fb5 100644 --- a/source/backend/lighting/photonshootingtask.cpp +++ b/source/backend/lighting/photonshootingtask.cpp @@ -54,6 +54,7 @@ #include "core/scene/object.h" #include "core/shape/csg.h" #include "core/support/octree.h" +#include "core/support/statistics.h" // POV-Ray header files (POVMS module) #include "povms/povmscpp.h" diff --git a/source/backend/povray.cpp b/source/backend/povray.cpp index 7b7690db7..dc0e1a299 100644 --- a/source/backend/povray.cpp +++ b/source/backend/povray.cpp @@ -41,9 +41,9 @@ // C++ standard header files #include +#include // Boost header files -#include #include // POV-Ray header files (base module) @@ -216,7 +216,7 @@ volatile POVMSContext POV_RenderContext = nullptr; volatile POVMSAddress POV_FrontendAddress = POVMSInvalidAddress; /// Main POV-Ray thread that waits for messages from the frontend -boost::thread *POV_MainThread = nullptr; +std::thread *POV_MainThread = nullptr; /// Flag to mark main POV-Ray thread for termination volatile bool POV_TerminateMainThread = false; @@ -610,7 +610,7 @@ void MainThreadFunction(const boost::function0& threadExit) (void)POVMS_ASSERT_OUTPUT("Unhandled exception in POVMS receive handler in main POV-Ray backend thread.", __FILE__, __LINE__); } - boost::thread::yield(); + std::this_thread::yield(); } // close_all(); // TODO FIXME - Remove this call! [trf] @@ -642,7 +642,7 @@ void MainThreadFunction(const boost::function0& threadExit) } // namespace -boost::thread *povray_init(const boost::function0& threadExit, POVMSAddress *addr) +std::thread *povray_init(const boost::function0& threadExit, POVMSAddress *addr) { using namespace pov; @@ -654,13 +654,13 @@ boost::thread *povray_init(const boost::function0& threadExit, POVMSAddres Initialize_Noise(); pov::InitializePatternGenerators(); - POV_MainThread = Task::NewBoostThread(boost::bind(&MainThreadFunction, threadExit), POV_THREAD_STACK_SIZE); + POV_MainThread = new std::thread(boost::bind(&MainThreadFunction, threadExit)); - // we can't depend on boost::thread::yield here since under windows it is not - // guaranteed to give up a time slice [see API docs for Sleep(0)] + // We can't depend on `std::this_thread::yield()` here since it is not + // guaranteed to give up a time slice. while (POV_RenderContext == nullptr) { - boost::thread::yield(); + std::this_thread::yield(); pov_base::Delay(50); } } @@ -688,7 +688,7 @@ void povray_terminate() while (POV_RenderContext != nullptr) { - boost::thread::yield(); + std::this_thread::yield(); pov_base::Delay(100); } diff --git a/source/backend/povray.h b/source/backend/povray.h index eb53108da..f60fb43b0 100644 --- a/source/backend/povray.h +++ b/source/backend/povray.h @@ -46,14 +46,16 @@ #include "backend/configbackend.h" // C++ variants of C standard header files -// C++ standard header files // (none at the moment) +// C++ standard header files +// not required for `std::thread` because we forward-declare it in `base/base_fwd.h` + // Boost header files -#include #include // POV-Ray header files (base module) +#include "base/base_fwd.h" #include "base/version_info.h" // POV-Ray header files (backend module) @@ -66,7 +68,7 @@ * @param addr If not `nullptr`, backend address on return. * @return Pointer to the thread resource created. */ -boost::thread *povray_init(const boost::function0& threadExit, POVMSAddress *addr = nullptr); +std::thread *povray_init(const boost::function0& threadExit, POVMSAddress *addr = nullptr); /** * This function shuts down the main render thread and after it has diff --git a/source/backend/precomp.h b/source/backend/precomp.h index f9397f771..0976c7677 100644 --- a/source/backend/precomp.h +++ b/source/backend/precomp.h @@ -59,25 +59,20 @@ // C++ standard header files #include -#include +#include +#include #include #include #include +#include #include #include #include #include #include +#include #include // Boost header files #include -#include #include -#include -#if POV_MULTITHREADED -#include -#include -#endif -#include - diff --git a/source/backend/render/radiositytask.cpp b/source/backend/render/radiositytask.cpp index fc706957e..a6d8262a2 100644 --- a/source/backend/render/radiositytask.cpp +++ b/source/backend/render/radiositytask.cpp @@ -43,15 +43,13 @@ #include #include -// Boost header files -#include -#include - // POV-Ray header files (base module) #include "base/timer.h" #include "base/types.h" // POV-Ray header files (core module) +#include "core/support/statistics.h" + // POV-Ray header files (POVMS module) // (none at the moment) diff --git a/source/backend/render/rendertask.cpp b/source/backend/render/rendertask.cpp index 9219624bc..dcc9da4b7 100644 --- a/source/backend/render/rendertask.cpp +++ b/source/backend/render/rendertask.cpp @@ -41,7 +41,6 @@ // (none at the moment) // Boost header files -#include #include // POV-Ray header files (base module) diff --git a/source/backend/render/tracetask.cpp b/source/backend/render/tracetask.cpp index 063404981..b73119de4 100644 --- a/source/backend/render/tracetask.cpp +++ b/source/backend/render/tracetask.cpp @@ -43,9 +43,6 @@ #include #include -// Boost header files -#include - // POV-Ray header files (base module) #include "base/image/colourspace.h" #ifdef PROFILE_INTERSECTIONS @@ -58,6 +55,7 @@ #include "core/math/jitter.h" #include "core/math/matrix.h" #include "core/render/trace.h" +#include "core/support/statistics.h" // POV-Ray header files (POVMS module) // (none at the moment) diff --git a/source/backend/scene/backendscenedata.cpp b/source/backend/scene/backendscenedata.cpp index e2829156a..b0c7a54af 100644 --- a/source/backend/scene/backendscenedata.cpp +++ b/source/backend/scene/backendscenedata.cpp @@ -43,10 +43,6 @@ #include #include -// Boost header files -#include -#include - // POV-Ray header files (base module) #include "base/fileinputoutput.h" #include "base/fileutil.h" diff --git a/source/backend/scene/view.cpp b/source/backend/scene/view.cpp index f1b693085..8500f8a23 100644 --- a/source/backend/scene/view.cpp +++ b/source/backend/scene/view.cpp @@ -41,12 +41,11 @@ // C++ standard header files #include +#include +#include // Boost header files -#include #include -#include -#include #include // POV-Ray header files (base module) @@ -237,7 +236,7 @@ void ViewData::getBlockXY(const unsigned int nb, unsigned int &x, unsigned int & bool ViewData::GetNextRectangle(POVRect& rect, unsigned int& serial) { - boost::mutex::scoped_lock lock(nextBlockMutex); + std::lock_guard lock(nextBlockMutex); while(true) { @@ -274,7 +273,7 @@ bool ViewData::GetNextRectangle(POVRect& rect, unsigned int& serial) bool ViewData::GetNextRectangle(POVRect& rect, unsigned int& serial, BlockInfo*& blockInfo, unsigned int stride) { - boost::mutex::scoped_lock lock(nextBlockMutex); + std::lock_guard lock(nextBlockMutex); BlockIdSet newPostponedList; @@ -535,7 +534,7 @@ void ViewData::CompletedRectangle(const POVRect& rect, unsigned int serial, cons void ViewData::CompletedRectangle(const POVRect& rect, unsigned int serial, float completion, BlockInfo* blockInfo) { { - boost::mutex::scoped_lock lock(nextBlockMutex); + std::lock_guard lock(nextBlockMutex); blockBusyList.erase(serial); blockInfoList[serial] = blockInfo; } @@ -578,7 +577,7 @@ void ViewData::SetNextRectangle(const BlockIdSet& bsl, unsigned int fs) void ViewData::SetHighestTraceLevel(unsigned int htl) { - boost::mutex::scoped_lock lock(setDataMutex); + std::lock_guard lock(setDataMutex); highestTraceLevel = max(highestTraceLevel, htl); } @@ -709,7 +708,7 @@ void View::StartRender(POVMS_Object& renderOptions) shared_ptr blockskiplist(new ViewData::BlockIdSet()); if (renderControlThread == nullptr) - renderControlThread = Task::NewBoostThread(boost::bind(&View::RenderControlThread, this), POV_THREAD_STACK_SIZE); + renderControlThread = new std::thread(boost::bind(&View::RenderControlThread, this)); viewData.qualityFlags = QualityFlags(clip(renderOptions.TryGetInt(kPOVAttrib_Quality, 9), 0, 9)); @@ -738,11 +737,11 @@ void View::StartRender(POVMS_Object& renderOptions) seed = renderOptions.TryGetInt(kPOVAttrib_StochasticSeed, 0); if (seed == 0) - { - boost::posix_time::ptime now = boost::posix_time::second_clock::universal_time(); - boost::posix_time::ptime base = boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1)); - seed = (now - base).total_seconds(); - } + // The following expression returns the number of _ticks_ elapsed since + // the system clock's _epoch_, where a _tick_ is the platform-dependent + // shortest time interval the system clock can measure, and _epoch_ is a + // platform-dependent point in time (usually 1970-01-01 00:00:00). + seed = std::chrono::system_clock::now().time_since_epoch().count(); // TODO FIXME - [CLi] handle loading, storing (and later optionally deleting) of radiosity cache file for trace abort & continue feature // TODO FIXME - [CLi] if high reproducibility is a demand, timing of writing samples to disk is an issue regarding abort & continue @@ -1462,7 +1461,7 @@ void View::RenderControlThread() if(stopRequsted == false) { - boost::thread::yield(); + std::this_thread::yield(); Delay(50); } } @@ -1495,14 +1494,14 @@ RTRData::~RTRData() // lead to all threads ending up waiting on the condition). const Camera *RTRData::CompletedFrame() { - boost::mutex::scoped_lock lock (counterMutex); + std::unique_lock lock (counterMutex); vector& cameras = viewData.GetSceneData()->cameras; bool ca = viewData.GetSceneData()->clocklessAnimation; if(true) // yes I know it's not needed, but I prefer this over headless code blocks { - // test >= in case of weirdness due to the timed wait we use with the boost::condition + // test >= in case of weirdness due to the timed wait we use with the std::condition_variable if (++numRenderThreadsCompleted >= numRenderThreads) { viewData.SetNextRectangle(ViewData::BlockIdSet(), 0); @@ -1549,16 +1548,11 @@ const Camera *RTRData::CompletedFrame() } } - // TODO FIXME - boost::xtime has been deprecated since boost 1.34. - boost::xtime t; - boost::xtime_get (&t, POV_TIME_UTC); - t.sec += 3; - // this will cause us to wait until the other threads are done. // we use a timed lock so that we eventually pick up a render cancel request. // if we do exit as a result of a timeout, and there is not a cancel pending, // things could get out of whack. - if (!event.timed_wait(lock, t)) + if (event.wait_for(lock, std::chrono::seconds(3)) == std::cv_status::timeout) numRenderThreadsCompleted--; return (ca ? &cameras[numRTRframes % cameras.size()] : nullptr); diff --git a/source/backend/scene/view.h b/source/backend/scene/view.h index c5fb4164c..a2b5931cc 100644 --- a/source/backend/scene/view.h +++ b/source/backend/scene/view.h @@ -44,10 +44,14 @@ // (none at the moment) // C++ standard header files +#include #include +#include +// not required for `std::thread` because we forward-declare it in `base/base_fwd.h` #include // POV-Ray header files (base module) +#include "base/base_fwd.h" #include "base/types.h" // TODO - only appears to be pulled in for POVRect - can we avoid this? // POV-Ray header files (core module) @@ -85,9 +89,9 @@ class RTRData final private: ViewData& viewData; - boost::mutex counterMutex; - boost::mutex eventMutex; - boost::condition event; + std::mutex counterMutex; + std::mutex eventMutex; + std::condition_variable event; int width; int height; unsigned int numPixelsCompleted; @@ -304,9 +308,9 @@ class ViewData final /// repeating the process until a value is reached that is not found in @ref blockSkipList. volatile unsigned int nextBlock; /// next block counter mutex - boost::mutex nextBlockMutex; + std::mutex nextBlockMutex; /// set data mutex - boost::mutex setDataMutex; + std::mutex setDataMutex; /// Whether all blocks have been dispatched at least once. bool completedFirstPass; /// highest reached trace level @@ -459,7 +463,7 @@ class View final /// stop request flag bool stopRequsted; /// render control thread - boost::thread *renderControlThread; + std::thread *renderControlThread; /// BSP tree mailbox BSPTree::Mailbox mailbox; diff --git a/source/backend/support/task.cpp b/source/backend/support/task.cpp index f6732d71a..72c3065a3 100644 --- a/source/backend/support/task.cpp +++ b/source/backend/support/task.cpp @@ -41,10 +41,10 @@ // C++ standard header files #include +#include // Boost header files #include -#include // POV-Ray header files (base module) #include "base/povassert.h" @@ -113,7 +113,7 @@ POV_LONG Task::ConsumedCPUTime() const void Task::Start(const boost::function0& completion) { if ((done == false) && (taskThread == nullptr)) - taskThread = NewBoostThread(boost::bind(&Task::TaskThread, this, completion), POV_THREAD_STACK_SIZE); + taskThread = new std::thread(boost::bind(&Task::TaskThread, this, completion)); } void Task::RequestStop() @@ -143,6 +143,22 @@ void Task::Resume() paused = false; } +void Task::Cooperate() +{ + if (stopRequested == true) + throw StopThreadException(); + else if (paused == true) + { + while (paused == true) + { + std::this_thread::yield(); + Delay(100); + if (stopRequested == true) + throw StopThreadException(); + } + } +} + POV_LONG Task::ElapsedRealTime() const { POV_TASK_ASSERT(timer != nullptr); diff --git a/source/backend/support/task.h b/source/backend/support/task.h index 14a2f6904..6fec0194b 100644 --- a/source/backend/support/task.h +++ b/source/backend/support/task.h @@ -45,9 +45,9 @@ // C++ standard header files #include #include +// not required for `std::thread` because we forward-declare it in `base/base_fwd.h` // Boost header files -#include #include // POV-Ray header files (base module) @@ -86,45 +86,12 @@ class Task void Stop(); void Pause(); void Resume(); - - inline void Cooperate() - { - if(stopRequested == true) - throw StopThreadException(); - else if(paused == true) - { - while(paused == true) - { - boost::thread::yield(); - Delay(100); - if(stopRequested == true) - throw StopThreadException(); - } - } - } + void Cooperate(); inline ThreadData *GetDataPtr() { return taskData; } inline POVMSContext GetPOVMSContext() { return povmsContext; } - /// Start a new thread with a given stack size. - template - inline static boost::thread* NewBoostThread(CALLABLE_T func, int stackSize) - { -#if HAVE_BOOST_THREAD_ATTRIBUTES - // boost 1.50 and later provide an official mechanism to set the stack size. - boost::thread::attributes attr; - attr.set_stack_size (stackSize); - return new boost::thread(attr, func); -#elif !defined(USE_OFFICIAL_BOOST) - // Prior to boost 1.50, for some platforms we used an unofficial hacked version of boost to set the stack size. - return new boost::thread(func, stackSize); -#else - // For some platforms the default stack size of older boost versions may suffice. - return new boost::thread(func); -#endif - } - protected: struct StopThreadException final {}; // TODO - consider subclassing from std::exception hierarchy. @@ -157,7 +124,7 @@ class Task // CPU time spend in task POV_LONG cpuTime; /// task thread - boost::thread *taskThread; + std::thread *taskThread; /// POVMS message receiving context POVMSContext povmsContext; diff --git a/source/backend/support/taskqueue.cpp b/source/backend/support/taskqueue.cpp index 9db706040..80db09b93 100644 --- a/source/backend/support/taskqueue.cpp +++ b/source/backend/support/taskqueue.cpp @@ -40,7 +40,6 @@ // C++ standard header files // Boost header files -#include #include // POV-Ray header files (base module) @@ -71,7 +70,7 @@ TaskQueue::~TaskQueue() void TaskQueue::Stop() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); // we pass through this list twice; the first time through only sets the cancel // flag, and the second time through waits for the threads to exit. if we only @@ -93,7 +92,7 @@ void TaskQueue::Stop() void TaskQueue::Pause() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); for(list::iterator i(activeTasks.begin()); i != activeTasks.end(); i++) i->GetTask()->Pause(); @@ -101,7 +100,7 @@ void TaskQueue::Pause() void TaskQueue::Resume() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); for(list::iterator i(activeTasks.begin()); i != activeTasks.end(); i++) i->GetTask()->Resume(); @@ -109,7 +108,7 @@ void TaskQueue::Resume() bool TaskQueue::IsPaused() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); bool paused = false; @@ -121,7 +120,7 @@ bool TaskQueue::IsPaused() bool TaskQueue::IsRunning() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); bool running = !queuedTasks.empty(); @@ -133,7 +132,7 @@ bool TaskQueue::IsRunning() bool TaskQueue::IsDone() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); bool done = queuedTasks.empty(); @@ -145,14 +144,14 @@ bool TaskQueue::IsDone() bool TaskQueue::Failed() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); return (failed != kNoError); } int TaskQueue::FailureCode(int defval) { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); if(failed == kNoError) return defval; @@ -162,7 +161,7 @@ int TaskQueue::FailureCode(int defval) ThreadData *TaskQueue::AppendTask(Task *task) { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); failed = false; @@ -175,7 +174,7 @@ ThreadData *TaskQueue::AppendTask(Task *task) void TaskQueue::AppendSync() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); queuedTasks.push(TaskEntry::kSync); @@ -184,7 +183,7 @@ void TaskQueue::AppendSync() void TaskQueue::AppendMessage(POVMS_Message& msg) { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); queuedTasks.push(TaskEntry(msg)); @@ -193,7 +192,7 @@ void TaskQueue::AppendMessage(POVMS_Message& msg) void TaskQueue::AppendFunction(const boost::function1& fn) { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::lock_guard lock(queueMutex); queuedTasks.push(TaskEntry(fn)); @@ -202,7 +201,7 @@ void TaskQueue::AppendFunction(const boost::function1& fn) bool TaskQueue::Process() { - boost::recursive_mutex::scoped_lock lock(queueMutex); + std::unique_lock lock(queueMutex); for(list::iterator i(activeTasks.begin()); i != activeTasks.end();) { diff --git a/source/backend/support/taskqueue.h b/source/backend/support/taskqueue.h index ba482a311..a5a0ae457 100644 --- a/source/backend/support/taskqueue.h +++ b/source/backend/support/taskqueue.h @@ -43,13 +43,14 @@ // (none at the moment) // C++ standard header files +#include #include #include +#include #include // Boost header files -#include -#include +#include // POV-Ray header files (base module) // (none at the moment) @@ -122,11 +123,11 @@ class TaskQueue final /// active task list std::list activeTasks; /// queue mutex - boost::recursive_mutex queueMutex; + std::recursive_mutex queueMutex; /// failed code int failed; /// wait for data in queue or related operation to be processed - boost::condition processCondition; + std::condition_variable_any processCondition; TaskQueue(const TaskQueue&) = delete; TaskQueue& operator=(const TaskQueue&) = delete; diff --git a/source/base/base_fwd.h b/source/base/base_fwd.h index c71b98949..37622eea9 100644 --- a/source/base/base_fwd.h +++ b/source/base/base_fwd.h @@ -40,6 +40,14 @@ /// @note /// This file should not pull in any POV-Ray header whatsoever. +// Forward-declare the standard library's thread type, rather than pulling in +// ``, and all the other headers it might want in turn. +namespace std +{ +class thread; +} +// end of namespace std + namespace pov_base { diff --git a/source/base/configbase.h b/source/base/configbase.h index 18b9bae02..d83b18e06 100644 --- a/source/base/configbase.h +++ b/source/base/configbase.h @@ -45,9 +45,6 @@ // C++ standard header files // (none at the moment) -// Boost header files -#include - //############################################################################## /// /// @defgroup PovBaseConfig Base Compile-Time Configuration @@ -67,7 +64,6 @@ /// - `POV_MALLOC` /// - `POV_REALLOC` /// - `POV_FREE` -/// - `POV_MEMMOVE` /// /// @{ @@ -87,6 +83,7 @@ #define POV_CPP11_SUPPORTED (__cplusplus >= 201103L) #endif + /// @} /// //****************************************************************************** @@ -510,15 +507,6 @@ #define POV_STRDUP(str) pov_base::pov_strdup(str) #endif -// For those systems that don't have memmove, this can also be pov_memmove -#ifndef POV_MEMMOVE - #define POV_MEMMOVE(dst,src,len) pov_base::pov_memmove((dst),(src),(len)) -#endif - -#ifndef POV_MEMCPY - #define POV_MEMCPY(dst,src,len) std::memcpy((dst),(src),(len)) -#endif - #ifndef POV_MEM_STATS #define POV_MEM_STATS 0 #define POV_GLOBAL_MEM_STATS(a,f,c,p,s,l) (false) @@ -708,17 +696,6 @@ #define CDECL #endif -#ifndef ALIGN16 - #define ALIGN16 -#endif - -#ifndef ALIGN32 - // leave undefined, allowing code to detect that forced 32-bit alignment isn't supported - // The following two lines work around doxygen being unable to document undefined macros. - #define ALIGN32 (undefined) - #undef ALIGN32 -#endif - #ifndef FORCEINLINE #define FORCEINLINE inline #endif @@ -733,18 +710,29 @@ #define POV_MULTITHREADED 1 #endif -/// @def POV_USE_DEFAULT_DELAY -/// Whether to use a default implementation for the millisecond-precision delay function. +/// @def POV_USE_PLATFORM_DELAY +/// Whether to use a platform-specific implementation for the millisecond-precision delay function. /// -/// Define as non-zero to use a default implementation for the @ref pov_base::Delay() function, or zero if +/// Define as zero to use a portable default implementation for the @ref pov_base::Delay() function, or non-zero if /// the platform provides its own implementation. /// -/// @note -/// The default implementation is only provided as a last-ditch resort. Wherever possible, -/// implementations should provide their own implementation. +/// The actual value may carry additional semantics based on the platform +/// family. The following are currently known (but see the respective platform +/// specific code for authoritative information): +/// +/// | Value | Windows | Unix | +/// | ----: | :------------ | :---------------- | +/// | 0 | `std::this_thread::sleep_for()` | +/// | 1 | `Sleep()` | `nanosleep()` | +/// | 2 | ^ | `usleep()` | +/// | other | ^ | undefined | /// -#ifndef POV_USE_DEFAULT_DELAY - #define POV_USE_DEFAULT_DELAY 1 +#ifndef POV_USE_PLATFORM_DELAY + #define POV_USE_PLATFORM_DELAY 0 +#endif + +#ifdef POV_USE_DEFAULT_DELAY +#error "POV_USE_DEFAULT_DELAY has been superseded by POV_USE_PLATFORM_DELAY. Note that the new setting has inverse semantics." #endif /// @def POV_USE_DEFAULT_TIMER @@ -926,24 +914,6 @@ /// /// @{ -/// @def POV_TIME_UTC -/// Alias for `boost::TIME_UTC` or `boost::TIME_UTC_`, whichever is applicable. -/// -/// Boost 1.50 changed TIME_UTC to TIME_UTC_ to avoid a clash with C++11, which has -/// TIME_UTC as a define (in boost it's an enum). To allow compilation with earlier -/// versions of boost we now use POV_TIME_UTC in the code and define that here. -/// -#if BOOST_VERSION >= 105000 - #define POV_TIME_UTC boost::TIME_UTC_ -#else - #ifdef TIME_UTC - // clash between C++11 and boost detected, need to hard-code - #define POV_TIME_UTC 1 - #else - #define POV_TIME_UTC boost::TIME_UTC - #endif -#endif - /// @def POV_BACKSLASH_IS_PATH_SEPARATOR /// Whether the system supports the backslash as a separator character. /// diff --git a/source/base/filesystem_fwd.h b/source/base/filesystem_fwd.h index 08ac0a636..0a6053ae1 100644 --- a/source/base/filesystem_fwd.h +++ b/source/base/filesystem_fwd.h @@ -36,12 +36,13 @@ #ifndef POVRAY_BASE_FILESYSTEM_FWD_H #define POVRAY_BASE_FILESYSTEM_FWD_H -// C++ standard header files -#include - /// @file /// @note -/// This file should not pull in any POV-Ray header whatsoever. +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). + +// C++ standard header files +#include namespace pov_base { diff --git a/source/base/image/colourspace.cpp b/source/base/image/colourspace.cpp index eadbb7d32..6d12c48d7 100644 --- a/source/base/image/colourspace.cpp +++ b/source/base/image/colourspace.cpp @@ -57,9 +57,7 @@ using std::max; // definitions of static GammaCurve member variables to satisfy the linker std::list> GammaCurve::cache; -#if POV_MULTITHREADED -boost::mutex GammaCurve::cacheMutex; -#endif +std::mutex GammaCurve::cacheMutex; // definitions of static GammaCurve-derivatives' member variables to satisfy the linker SimpleGammaCurvePtr NeutralGammaCurve::instance; @@ -77,10 +75,8 @@ float* GammaCurve::GetLookupTable(unsigned int max) // Get a reference to the lookup table pointer we're dealing with, so we don't need to duplicate all the remaining code. float*& lookupTable = (max == 255 ? lookupTable8 : lookupTable16); -#if POV_MULTITHREADED // Make sure we're not racing any other thread that might currently be busy creating the LUT. - boost::mutex::scoped_lock lock(lutMutex); -#endif + std::lock_guard lock(lutMutex); // Create the LUT if it doesn't exist yet. if (!lookupTable) @@ -102,12 +98,10 @@ GammaCurvePtr GammaCurve::GetMatching(const GammaCurvePtr& newInstance) GammaCurvePtr oldInstance; bool cached = false; - // See if we have a matching gamma curve in our chache already + // See if we have a matching gamma curve in our cache already -#if POV_MULTITHREADED // make sure the cache doesn't get tampered with while we're working on it - boost::mutex::scoped_lock lock(cacheMutex); -#endif + std::lock_guard lock(cacheMutex); // Check if we already have created a matching gamma curve object; if so, return that object instead. // Also, make sure we get the new object stored (as we're using weak pointers, we may have stale entries; diff --git a/source/base/image/colourspace.h b/source/base/image/colourspace.h index 21a2d16e8..b7f46c2b0 100644 --- a/source/base/image/colourspace.h +++ b/source/base/image/colourspace.h @@ -46,11 +46,7 @@ // C++ standard header files #include #include - -// Boost header files -#if POV_MULTITHREADED -#include -#endif +#include // POV-Ray header files (base module) #include "base/colour.h" @@ -306,7 +302,7 @@ class GammaCurve #if POV_MULTITHREADED /// Mutex to guard access to @ref lookupTable8 and @ref lookupTable16. - boost::mutex lutMutex; + std::mutex lutMutex; #endif /// Constructor. @@ -341,7 +337,7 @@ class GammaCurve #if POV_MULTITHREADED /// Mutex to guard access to `cache`. - static boost::mutex cacheMutex; + static std::mutex cacheMutex; #endif /// Function to manage the gamma curve cache. @@ -570,7 +566,7 @@ class TranscodingGammaCurve final : public GammaCurve protected: GammaCurvePtr workGamma; GammaCurvePtr encGamma; - TranscodingGammaCurve(); + TranscodingGammaCurve() = delete; TranscodingGammaCurve(const GammaCurvePtr&, const GammaCurvePtr&); virtual bool Matches(const GammaCurvePtr&) const override; }; diff --git a/source/base/image/colourspace_fwd.h b/source/base/image/colourspace_fwd.h index 55ee33371..efde5724c 100644 --- a/source/base/image/colourspace_fwd.h +++ b/source/base/image/colourspace_fwd.h @@ -36,12 +36,13 @@ #ifndef POVRAY_BASE_COLOURSPACE_FWD_H #define POVRAY_BASE_COLOURSPACE_FWD_H -// C++ standard header files -#include - /// @file /// @note -/// This file should not pull in any POV-Ray header whatsoever. +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). + +// C++ standard header files +#include namespace pov_base { diff --git a/source/base/image/dither_fwd.h b/source/base/image/dither_fwd.h index 5e568b37a..d953b5d0e 100644 --- a/source/base/image/dither_fwd.h +++ b/source/base/image/dither_fwd.h @@ -36,12 +36,13 @@ #ifndef POVRAY_BASE_DITHER_FWD_H #define POVRAY_BASE_DITHER_FWD_H -// C++ standard header files -#include - /// @file /// @note -/// This file should not pull in any POV-Ray header whatsoever. +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). + +// C++ standard header files +#include namespace pov_base { diff --git a/source/base/image/metadata.h b/source/base/image/metadata.h index 6520c8fed..8cbc482d7 100644 --- a/source/base/image/metadata.h +++ b/source/base/image/metadata.h @@ -46,7 +46,6 @@ #include // Boost header files -#include #include // POV-Ray header files (base module) diff --git a/source/base/image/tiff.cpp b/source/base/image/tiff.cpp index 5f6b26e61..59a2ea5ae 100644 --- a/source/base/image/tiff.cpp +++ b/source/base/image/tiff.cpp @@ -45,9 +45,6 @@ #include #include -// Boost header files -#include - // Other 3rd party header files extern "C" { diff --git a/source/base/pov_mem.cpp b/source/base/pov_mem.cpp index 838eea34e..6ef58371f 100644 --- a/source/base/pov_mem.cpp +++ b/source/base/pov_mem.cpp @@ -739,7 +739,7 @@ void *pov_memmove (void *dest, const void *src, size_t length) while (length > 0) { - POV_MEMCPY(cdest + length - size, csrc + length - size, size); + std::memcpy(cdest + length - size, csrc + length - size, size); length -= size; @@ -758,7 +758,7 @@ void *pov_memmove (void *dest, const void *src, size_t length) while (length > 0) { - POV_MEMCPY(new_dest, csrc, length); + std::memcpy(new_dest, csrc, length); new_dest += size; csrc += size; @@ -770,7 +770,7 @@ void *pov_memmove (void *dest, const void *src, size_t length) } else { - POV_MEMCPY(cdest, csrc, length); + std::memcpy(cdest, csrc, length); } return cdest; diff --git a/source/base/pov_mem.h b/source/base/pov_mem.h index 6b3fa5267..8d9a5ee16 100644 --- a/source/base/pov_mem.h +++ b/source/base/pov_mem.h @@ -46,6 +46,7 @@ // C++ variants of C standard header files #include +#include // C++ standard header files // (none at the moment) diff --git a/source/base/precomp.h b/source/base/precomp.h index 9c8636a86..fbd0b30bf 100644 --- a/source/base/precomp.h +++ b/source/base/precomp.h @@ -59,10 +59,9 @@ // C++ standard header files #include -#include #include -#include #include +#include #include #include #include @@ -71,12 +70,4 @@ #include // Boost header files -#include -#include -#include -#include -#if POV_MULTITHREADED -#include -#include -#endif -#include +#include diff --git a/source/base/stringutilities.h b/source/base/stringutilities.h index d0b20f8c1..33f38baa0 100644 --- a/source/base/stringutilities.h +++ b/source/base/stringutilities.h @@ -45,9 +45,6 @@ // C++ standard header files #include -// Boost header files -// (none at the moment) - // POV-Ray header files (base module) #include "base/base_fwd.h" #include "base/povassert.h" @@ -250,7 +247,8 @@ bool IsUCSLowSurrogate(UCS4 character); /// @return `true` if the code point qualifies as a UCS scalar value. bool IsUCSScalarValue(UCS4 character); -} // end of namespace UCS +} +// end of namespace UCS //****************************************************************************** diff --git a/source/base/timer.cpp b/source/base/timer.cpp index 2ffe0270b..812fba7fc 100644 --- a/source/base/timer.cpp +++ b/source/base/timer.cpp @@ -37,12 +37,12 @@ #include "base/timer.h" // C++ variants of C standard header files -// C++ standard header files // (none at the moment) -// Boost header files -#if POV_MULTITHREADED -#include +// C++ standard header files +#if !POV_USE_PLATFORM_DELAY +#include +#include #endif // POV-Ray header files (base module) @@ -54,46 +54,36 @@ namespace pov_base { -#if POV_MULTITHREADED && POV_USE_DEFAULT_DELAY +//****************************************************************************** + +#if !POV_USE_PLATFORM_DELAY void Delay(unsigned int msec) { - boost::xtime t; - boost::xtime_get(&t, POV_TIME_UTC); - POV_ULONG ns = (POV_ULONG)(t.sec) * (POV_ULONG)(1000000000) + (POV_ULONG)(t.nsec) + (POV_ULONG)(msec) * (POV_ULONG)(1000000); - t.sec = (boost::xtime::xtime_sec_t)(ns / (POV_ULONG)(1000000000)); - t.nsec = (boost::xtime::xtime_nsec_t)(ns % (POV_ULONG)(1000000000)); - boost::thread::sleep(t); + std::this_thread::sleep_for(std::chrono::milliseconds(msec)); } -#endif // POV_MULTITHREADED && POV_USE_DEFAULT_DELAY +#endif // POV_USE_PLATFORM_DELAY -#if POV_USE_DEFAULT_TIMER +//****************************************************************************** -Timer::Timer() +DefaultRealTimer::DefaultRealTimer() { Reset(); } -Timer::~Timer() +POV_LONG DefaultRealTimer::ElapsedTime() const { + auto elapsed = std::chrono::steady_clock::now() - mRealTimeStart; + return std::chrono::duration_cast(elapsed).count(); } -POV_LONG Timer::ElapsedRealTime() const +void DefaultRealTimer::Reset() { - boost::xtime t; - boost::xtime_get(&t, POV_TIME_UTC); - POV_LONG tt = (POV_LONG)(t.sec) * (POV_LONG)(1000000000) + (POV_LONG)(t.nsec); - POV_LONG st = (POV_LONG)(mRealTimeStart.sec) * (POV_LONG)(1000000000) + (POV_LONG)(mRealTimeStart.nsec); - return ((tt - st) / (POV_LONG)(1000000)); + mRealTimeStart = std::chrono::steady_clock::now(); } -void Timer::Reset() -{ - boost::xtime_get(&mRealTimeStart, POV_TIME_UTC); -} - -#endif // POV_USE_DEFAULT_TIMER +//****************************************************************************** } // end of namespace pov_base diff --git a/source/base/timer.h b/source/base/timer.h index 6c0204349..7f6f8df2d 100644 --- a/source/base/timer.h +++ b/source/base/timer.h @@ -40,17 +40,13 @@ #include "base/configbase.h" // C++ variants of C standard header files -// C++ standard header files // (none at the moment) -// Boost header files -#if POV_USE_DEFAULT_TIMER -#include -#endif +// C++ standard header files +#include -#if !POV_USE_DEFAULT_TIMER || (POV_MULTITHREADED && !POV_USE_DEFAULT_DELAY) -#include "syspovtimer.h" -#endif +// NOTE: +// Another file is included at the end of this file. // POV-Ray header files (base module) // (none at the moment) @@ -65,47 +61,78 @@ namespace pov_base /// /// @{ -#if POV_MULTITHREADED && POV_USE_DEFAULT_DELAY - /// Wait for the specified time. /// -/// This function puts the current thread into idle mode for the specified time. +/// This function puts the current thread into idle mode for the specified time, +/// give or take. +/// +/// The default implementation is based on `std::this_thread::sleep_for`, which +/// should be good enough on most platforms. However, platforms can still +/// provide their own implementations, by setting @ref POV_USE_PLATFORM_DELAY to +/// non-zero and providing their own definition. /// /// @note -/// This is a default implementation, provided only as a last-ditch resort for platforms that -/// cannot provide a better implementation. +/// For low values (e.g. below 10 ms, but depending on implementation and +/// platform) this function may effectively be a no-op. /// -/// @todo -/// The current implementation is based on boost::xtime, which has been deprecated since -/// boost 1.34. +/// @param[in] msec Time to wait in milliseconds (0..999). /// -/// @attention -/// Due to possible limitations of platform-specific implementations, this function may only be -/// called to wait for less than 1 second. +void Delay(unsigned int msec); + +/// Default Millisecond-precision wall clock timer. /// -/// @attention -/// Due to possible limitations of platform-specific implementations, callers must not rely on -/// the duration to be exact, or even anywhere close. Most notably, the function may return -/// prematurely in case the thread receives a signal. +/// This class provides facilities to measure the elapsed wall clock time +/// since the object was created or last reset. /// -/// @param[in] msec Time to wait in milliseconds (0..999). +/// @note +/// This class should not be used directly. Instead, it is intended as a +/// building block for implementations of the @ref Timer class. /// -void Delay(unsigned int msec); +/// @impl +/// The current implementation is based on `std::chrono::steady_clock`. +/// +class DefaultRealTimer final +{ +public: + + /// Create and start a new timer. + DefaultRealTimer(); + + /// Report elapsed wall-clock time. + /// + /// This method reports the actual time in milliseconds that has elapsed + /// since the timer's creation or last call to @ref Reset(). + /// + /// @return Elapsed real time in milliseconds. + /// + POV_LONG ElapsedTime() const; + + /// Reset the timer. + void Reset(); + +private: -#endif // POV_MULTITHREADED && POV_USE_DEFAULT_DELAY + /// Point in time of construction or last reset. + std::chrono::steady_clock::time_point mRealTimeStart; +}; #if POV_USE_DEFAULT_TIMER /// Millisecond-precision timer. /// +/// This class provides facilities to measure the elapsed wall clock time, CPU +/// time used by the current process, and CPU time used by the current thread, +/// since the object was created or last reset. +/// +/// It is intended that platforms provide their own implementations, by setting +/// @ref POV_USE_DEFAULT_TIMER to non-zero, providing their own declaration in +/// `syspovtimer.h`, and providing their own definition. +/// /// @note -/// This is a default implementation, provided only as a last-ditch resort for platforms that +/// The default implementation is provided only as a last-ditch resort for platforms that /// cannot provide a better implementation. It can neither guarantee millisecond precision, nor /// does it support measurement of CPU time. /// -/// @todo -/// This implementation is based on boost::xtime, which has been deprecated since 1.34. -/// /// @impl /// Note that to measure per-process CPU time we're not resorting to `clock()` as a default /// implementation, as depending on the platform it may incorrectly report elapsed wall-clock @@ -119,11 +146,11 @@ class Timer final /// Create and start a new timer. /// - Timer(); + Timer() = default; /// Destroy the timer. /// - ~Timer(); + ~Timer() = default; /// Report elapsed wall-clock time. /// @@ -132,7 +159,7 @@ class Timer final /// /// @return Elapsed real time in milliseconds. /// - POV_LONG ElapsedRealTime() const; + inline POV_LONG ElapsedRealTime() const { return mRealTimer.ElapsedTime(); } /// Report CPU time consumed by current process. /// @@ -145,7 +172,7 @@ class Timer final /// /// @return Elapsed CPU time in milliseconds. /// - inline POV_LONG ElapsedProcessCPUTime() const { return ElapsedRealTime(); } + inline POV_LONG ElapsedProcessCPUTime() const { return mRealTimer.ElapsedTime(); } /// Report CPU time consumed by current thread. /// @@ -162,11 +189,11 @@ class Timer final /// /// @return Elapsed CPU time in milliseconds. /// - inline POV_LONG ElapsedThreadCPUTime() const { return ElapsedProcessCPUTime(); } + inline POV_LONG ElapsedThreadCPUTime() const { return mRealTimer.ElapsedTime(); } /// Reset the timer. /// - void Reset(); + inline void Reset() { mRealTimer.Reset(); } /// Report whether per-process measurement of CPU time is supported. /// @@ -190,8 +217,8 @@ class Timer final private: - /// real time at last reset - boost::xtime mRealTimeStart; + /// Point in time of construction or last reset. + DefaultRealTimer mRealTimer; }; #endif // POV_USE_DEFAULT_TIMER @@ -203,4 +230,9 @@ class Timer final } // end of namespace pov_base +// Need to include this last because it may require definitions from this file. +#if !POV_USE_DEFAULT_TIMER +#include "syspovtimer.h" +#endif + #endif // POVRAY_BASE_TIMER_H diff --git a/source/core/bounding/boundingbox.cpp b/source/core/bounding/boundingbox.cpp index d02901029..8152e17c5 100644 --- a/source/core/bounding/boundingbox.cpp +++ b/source/core/bounding/boundingbox.cpp @@ -42,6 +42,7 @@ // C++ variants of C standard header files #include +#include // C++ standard header files // (none at the moment) @@ -54,6 +55,7 @@ #include "core/render/ray.h" #include "core/scene/object.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" @@ -288,7 +290,7 @@ void Build_BBox_Tree(BBOX_TREE **Root, size_t numOfFiniteObjects, BBOX_TREE **&F { root = *Root; root->Node = reinterpret_cast(POV_REALLOC(root->Node, (root->Entries + 1) * sizeof(BBOX_TREE *), "composite")); - POV_MEMMOVE(&(root->Node[1]), &(root->Node[0]), root->Entries * sizeof(BBOX_TREE *)); + std::memmove(&(root->Node[1]), &(root->Node[0]), root->Entries * sizeof(BBOX_TREE *)); root->Entries++; cd = create_bbox_node(numOfInfiniteObjects); for(size_t i = 0; i < numOfInfiniteObjects; i++) diff --git a/source/core/configcore.h b/source/core/configcore.h index 284b0f3bb..ef3ef3bf4 100644 --- a/source/core/configcore.h +++ b/source/core/configcore.h @@ -243,7 +243,7 @@ /// /// The available implementations are based on the following primitives: /// -/// | Value | `Pow2Floor` | `BiasedIntLog2` | `BiasedIntPow2` | Bias | Prerequisites | +/// | Value | Pow2Floor | BiasedIntLog2 | BiasedIntPow2 | Bias | Prerequisites | /// | ----: | :---------------------------- | :-------- | :-------------------- | ----: | :------------------------------------ | /// | 0 | `float` bit bashing ||| +127 | `float` must be IEEE 754 "binary32" | /// | 1 | `logbf`, `pow` | `logbf` | `int` bit shifting | 0 | `float` must be radix-2 | diff --git a/source/core/core_fwd.h b/source/core/core_fwd.h index 28fe8da7f..d924029ea 100644 --- a/source/core/core_fwd.h +++ b/source/core/core_fwd.h @@ -43,6 +43,9 @@ namespace pov { +class GenericFunctionContext; +typedef GenericFunctionContext* GenericFunctionContextPtr; + class Interior; class Intersection; diff --git a/source/core/coretypes.h b/source/core/coretypes.h index f075ee7b0..3ba5cb219 100644 --- a/source/core/coretypes.h +++ b/source/core/coretypes.h @@ -599,8 +599,6 @@ class GenericFunctionContext virtual ~GenericFunctionContext() {} }; -typedef GenericFunctionContext* GenericFunctionContextPtr; - class GenericFunctionContextFactory { public: diff --git a/source/core/lighting/photons.cpp b/source/core/lighting/photons.cpp index b54dfe633..230858418 100644 --- a/source/core/lighting/photons.cpp +++ b/source/core/lighting/photons.cpp @@ -52,6 +52,7 @@ #include "core/lighting/lightsource.h" #include "core/material/interior.h" #include "core/material/normal.h" +#include "core/material/pattern.h" #include "core/material/pigment.h" #include "core/material/texture.h" #include "core/material/warp.h" @@ -62,6 +63,7 @@ #include "core/scene/tracethreaddata.h" #include "core/shape/csg.h" #include "core/support/octree.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/lighting/radiosity.cpp b/source/core/lighting/radiosity.cpp index f90aa086f..2063e24b3 100644 --- a/source/core/lighting/radiosity.cpp +++ b/source/core/lighting/radiosity.cpp @@ -79,6 +79,7 @@ #include "core/scene/scenedata.h" #include "core/scene/tracethreaddata.h" #include "core/support/octree.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" @@ -1045,7 +1046,7 @@ RadiosityCache::~RadiosityCache() { // mutex scope #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(fileMutex); + std::lock_guard lock(fileMutex); #endif // finish up cache file if (ot_fd != nullptr) @@ -1058,8 +1059,8 @@ RadiosityCache::~RadiosityCache() { // mutex scope #if POV_MULTITHREADED - boost::mutex::scoped_lock lockTree(octree.treeMutex); - boost::mutex::scoped_lock lockBlock(octree.blockMutex); + std::lock_guard lockTree(octree.treeMutex); + std::lock_guard lockBlock(octree.blockMutex); #endif if (octree.root != nullptr) ot_free_tree(&octree.root); @@ -1067,7 +1068,7 @@ RadiosityCache::~RadiosityCache() { // mutex scope #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(blockPoolsMutex); + std::lock_guard lock(blockPoolsMutex); #endif while (!blockPools.empty()) { @@ -1083,7 +1084,7 @@ RadiosityCache::~RadiosityCache() RadiosityCache::BlockPool* RadiosityCache::AcquireBlockPool() { #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(blockPoolsMutex); + std::lock_guard lock(blockPoolsMutex); #endif if (blockPools.empty()) return new BlockPool(); @@ -1099,14 +1100,14 @@ void RadiosityCache::ReleaseBlockPool(RadiosityCache::BlockPool* pool) { { // mutex scope #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(fileMutex); + std::lock_guard lock(fileMutex); #endif pool->Save(ot_fd); } { // mutex scope #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(blockPoolsMutex); + std::lock_guard lock(blockPoolsMutex); #endif blockPools.push_back(pool); } @@ -1238,7 +1239,7 @@ ot_node_struct *RadiosityCache::GetNode(RenderStatistics* stats, const ot_id_str ot_id_struct temp_id; #if POV_MULTITHREADED - boost::mutex::scoped_lock treeLock(octree.treeMutex, boost::defer_lock_t()); // we may need to lock this mutex - but not now. + std::unique_lock treeLock(octree.treeMutex, std::defer_lock); // we may need to lock this mutex - but not now. #endif #ifdef RADSTATS @@ -1420,7 +1421,7 @@ ot_node_struct *RadiosityCache::GetNode(RenderStatistics* stats, const ot_id_str void RadiosityCache::InsertBlock(ot_node_struct *node, ot_block_struct *block) { #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(octree.blockMutex); + std::lock_guard lock(octree.blockMutex); #endif block->next = node->Values; diff --git a/source/core/lighting/radiosity.h b/source/core/lighting/radiosity.h index 8689fcef0..64832c9e1 100644 --- a/source/core/lighting/radiosity.h +++ b/source/core/lighting/radiosity.h @@ -44,13 +44,9 @@ // C++ standard header files #include +#include #include -// Boost header files -#if POV_MULTITHREADED -#include -#endif - // POV-Ray header files (base module) #include "base/fileinputoutput_fwd.h" #include "base/path_fwd.h" @@ -231,8 +227,8 @@ class RadiosityCache final { ot_node_struct *root; #if POV_MULTITHREADED - boost::mutex treeMutex; // lock this when adding nodes to the tree - boost::mutex blockMutex; // lock this when adding blocks to any node of the tree + std::mutex treeMutex; // lock this when adding nodes to the tree + std::mutex blockMutex; // lock this when adding blocks to any node of the tree #endif Octree() : root(nullptr) {} @@ -240,14 +236,14 @@ class RadiosityCache final std::vector blockPools; // block pools ready to be re-used #if POV_MULTITHREADED - boost::mutex blockPoolsMutex; // lock this when accessing blockPools + std::mutex blockPoolsMutex; // lock this when accessing blockPools #endif Octree octree; OStream *ot_fd; #if POV_MULTITHREADED - boost::mutex fileMutex; // lock this when accessing ot_fd + std::mutex fileMutex; // lock this when accessing ot_fd #endif RadiosityRecursionSettings* recursionSettings; // dynamically allocated array; use recursion depth as index diff --git a/source/core/material/media.cpp b/source/core/material/media.cpp index c8572f7ad..9132565e2 100644 --- a/source/core/material/media.cpp +++ b/source/core/material/media.cpp @@ -52,7 +52,9 @@ #include "core/material/pigment.h" #include "core/math/chi2.h" #include "core/render/ray.h" +#include "core/scene/object.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/material/noise.cpp b/source/core/material/noise.cpp index 3b67f01bc..ff71e5c3c 100644 --- a/source/core/material/noise.cpp +++ b/source/core/material/noise.cpp @@ -92,10 +92,10 @@ static DBL *sintab; // GLOBAL VARIABLE #ifdef DYNAMIC_HASHTABLE unsigned short *hashTable; // GLOBAL VARIABLE #else -ALIGN16 unsigned short hashTable[8192]; // GLOBAL VARIABLE +alignas(16) unsigned short hashTable[8192]; // GLOBAL VARIABLE #endif -ALIGN16 DBL RTable[267*2] = +alignas(16) DBL RTable[267*2] = { -1, 0.0, 0.604974, 0.0, -0.937102, 0.0, 0.414115, 0.0, 0.576226, 0.0, -0.0161593, 0.0, 0.432334, 0.0, 0.103685, 0.0, 0.590539, 0.0, 0.0286412, 0.0, 0.46981, 0.0, -0.84622, 0.0, diff --git a/source/core/material/noise.h b/source/core/material/noise.h index 4a3f94e80..13dec5af9 100644 --- a/source/core/material/noise.h +++ b/source/core/material/noise.h @@ -97,10 +97,10 @@ const int NOISE_MINZ = NOISE_MINX; #ifdef DYNAMIC_HASHTABLE extern unsigned short *hashTable; #else -extern ALIGN16 unsigned short hashTable[8192]; +alignas(16) extern unsigned short hashTable[8192]; #endif -extern ALIGN16 DBL RTable[]; +alignas(16) extern DBL RTable[]; /***************************************************************************** diff --git a/source/core/material/normal.cpp b/source/core/material/normal.cpp index d39bad426..25bd58e1b 100644 --- a/source/core/material/normal.cpp +++ b/source/core/material/normal.cpp @@ -56,6 +56,7 @@ // POV-Ray header files (core module) #include "core/material/blendmap.h" #include "core/material/noise.h" +#include "core/material/pattern.h" #include "core/material/pigment.h" #include "core/material/warp.h" #include "core/scene/object.h" diff --git a/source/core/material/pattern.cpp b/source/core/material/pattern.cpp index fb55df1a1..5a2219715 100644 --- a/source/core/material/pattern.cpp +++ b/source/core/material/pattern.cpp @@ -65,7 +65,9 @@ #include "core/scene/object.h" #include "core/scene/scenedata.h" #include "core/scene/tracethreaddata.h" +#include "core/support/cracklecache.h" #include "core/support/imageutil.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" @@ -5746,7 +5748,7 @@ DBL CheckerPattern::Evaluate(const Vector3d& EPoint, const Intersection *pIsecti * neighbours from a set of disjoint points, like the membranes in suds are * to the centres of the bubbles). * -* All "crackle" specific source code and examples are in the public domain. +* The original "crackle" specific source code and examples are in the public domain. * * CHANGES * Oct 1994 : adapted from pigment by [CY] @@ -5795,36 +5797,30 @@ DBL CracklePattern::EvaluateRaw(const Vector3d& EPoint, const Intersection *pIse CrackleCacheEntry dummy_entry; CrackleCacheEntry* entry = &dummy_entry; - // search for this hash value in the cache - CrackleCache::iterator iter = pThread->mCrackleCache.find(ccoord); - if (iter == pThread->mCrackleCache.end()) - { - /* - * No, not same unit cube. Calculate the random points for this new - * cube and its 80 neighbours which differ in any axis by 1 or 2. - * Why distance of 2? If there is 1 point in each cube, located - * randomly, it is possible for the closest random point to be in the - * cube 2 over, or the one two over and one up. It is NOT possible - * for it to be two over and two up. Picture a 3x3x3 cube with 9 more - * cubes glued onto each face. - */ + if (pThread->mpCrackleCache->Lookup(entry, ccoord)) + { + // Cache hit. `entry` now points to the cached entry. + pThread->Stats()[CrackleCache_Tests_Succeeded]++; + } + else + { + // Cache miss. `entry` now points to a pristine entry set up in the + // cache, or to `dummy_entry` if the cache is too crowded already. + // In either case we need to fill in the blanks. - // generate a new cache entry, but only if the size of the cache is reasonable. - // having to re-calculate entries that would have been cache hits had we not - // skipped on adding an entry is less expensive than chewing up immense amounts - // of RAM and finally hitting the swapfile. unfortunately there's no good way - // to tell how much memory is 'too much' for the cache, so we just use a hard- - // coded number for now (ideally we should allow the user to configure this). - // keep in mind that the cache memory usage is per-thread, so the more threads, - // the more RAM. if we don't do the insert, entry will point at a local variable. - if (pThread->mCrackleCache.size() * sizeof(CrackleCache::value_type) < 30 * 1024 * 1024) - { - iter = pThread->mCrackleCache.insert(pThread->mCrackleCache.end(), CrackleCache::value_type(ccoord, CrackleCacheEntry())); - entry = &iter->second; - entry->lastUsed = pThread->ProgressIndex(); - } + // Calculate the random points for this new + // cube and its 80 neighbours which differ in any axis by 1 or 2. + // Why distance of 2? If there is 1 point in each cube, located + // randomly, it is possible for the closest random point to be in the + // cube 2 over, or the one two over and one up. It is NOT possible + // for it to be two over and two up. Picture a 3x3x3 cube with 9 more + // cubes glued onto each face. + + // TODO - Note that we're currently re-computing each cell up to 81 + // times - once as a main cell and 80 times as a neighbor - + // even in the best case scenario. Wouldn't it be more efficient + // to just cache the individual cells? - // see InitializeCrackleCubes() below. int *pc = gaCrackleCubeTable; for (int i = 0; i < 81; i++, pc += 3) { @@ -5854,11 +5850,6 @@ DBL CracklePattern::EvaluateRaw(const Vector3d& EPoint, const Intersection *pIse entry->aCellNuclei[i] += wrappingOffset; } } - else - { - pThread->Stats()[CrackleCache_Tests_Succeeded]++; - entry = &iter->second; - } // Find the 3 points with the 3 shortest distances from the input point. // Set up the loop so the invariant is true: minsum <= minsum2 <= minsum3 @@ -8915,6 +8906,7 @@ int PickInCube(const Vector3d& tv, Vector3d& p1) ******************************************************************************/ #ifndef HAVE_BOOST_HASH +// NOTE: Keep this around - we may need it when we get rid of boost::hash. static unsigned long int NewHash(long int tvx, long int tvy, long int tvz) { unsigned long int seed; diff --git a/source/core/material/pattern.h b/source/core/material/pattern.h index 95159fd93..72b708fba 100644 --- a/source/core/material/pattern.h +++ b/source/core/material/pattern.h @@ -44,10 +44,6 @@ // C++ standard header files // (none at the moment) -// Boost header files -#include // required for crackle -#include - // POV-Ray header files (base module) #include "base/fileinputoutput_fwd.h" @@ -1108,77 +1104,6 @@ struct ColourImagePattern final : public ColourPattern, public ImagePatternImpl }; -//****************************************************************************** -// Crackle Pattern Support Types - -/// Helper class to implement the crackle cache. -class CrackleCellCoord final -{ -public: - - CrackleCellCoord() : mX(0), mY(0), mZ(0), mRepeatX(0), mRepeatY(0), mRepeatZ(0) {} - CrackleCellCoord(int x, int y, int z, int rx, int ry, int rz) : mX(x), mY(y), mZ(z), mRepeatX(rx), mRepeatY(ry), mRepeatZ(rz) - { - WrapCellCoordinate(mX, mRepeatX); - WrapCellCoordinate(mY, mRepeatY); - WrapCellCoordinate(mZ, mRepeatZ); - } - - bool operator==(CrackleCellCoord const& other) const - { - return mX == other.mX && mY == other.mY && mZ == other.mZ; - } - - /// Function to compute a hash value from the coordinates. - /// - /// @note This function's name, as well as it being a global function rather than a member, is mandated by - /// boost::unordered_map. - /// - /// @param[in] coord The coordinate. - /// @return The hash. - /// - friend std::size_t hash_value(CrackleCellCoord const& coord) - { - std::size_t seed = 0; - boost::hash_combine(seed, coord.mX); - boost::hash_combine(seed, coord.mY); - boost::hash_combine(seed, coord.mZ); - - return seed; - } - -protected: - - int mX; - int mY; - int mZ; - int mRepeatX; - int mRepeatY; - int mRepeatZ; - - static inline void WrapCellCoordinate(int& v, int& repeat) - { - if (!repeat) - return; - v = wrapInt(v, repeat); - if ((v >= 2) && (v < repeat - 2)) - repeat = 0; - } -}; - -/// Helper class to implement the crackle cache. -struct CrackleCacheEntry final -{ - /// A kind of timestamp specifying when this particular entry was last used. - size_t lastUsed; - - /// The pseudo-random points defining the pattern in this particular subset of 3D space. - Vector3d aCellNuclei[81]; -}; - -typedef boost::unordered_map> CrackleCache; - - //****************************************************************************** // Legacy Global Functions diff --git a/source/core/material/pattern_fwd.h b/source/core/material/pattern_fwd.h index 17c99923e..befb79841 100644 --- a/source/core/material/pattern_fwd.h +++ b/source/core/material/pattern_fwd.h @@ -38,7 +38,8 @@ /// @file /// @note -/// This file should not pull in any POV-Ray header whatsoever. +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). namespace pov { diff --git a/source/core/math/jitter.h b/source/core/math/jitter.h index e02db55e7..3d0b8a1e0 100644 --- a/source/core/math/jitter.h +++ b/source/core/math/jitter.h @@ -60,7 +60,7 @@ namespace pov #ifdef DYNAMIC_HASHTABLE extern unsigned short *hashTable; // GLOBAL VARIABLE #else -extern ALIGN16 unsigned short hashTable[]; // GLOBAL VARIABLE +alignas(16) extern unsigned short hashTable[]; // GLOBAL VARIABLE #endif extern const float JitterTable[]; // GLOBAL VARIABLE diff --git a/source/core/math/randomsequence.cpp b/source/core/math/randomsequence.cpp index 512ab8aae..681587e87 100644 --- a/source/core/math/randomsequence.cpp +++ b/source/core/math/randomsequence.cpp @@ -42,6 +42,7 @@ // C++ standard header files #include #include +#include #include // Boost header files @@ -49,9 +50,6 @@ #include #include #include -#if POV_MULTITHREADED -#include -#endif // POV-Ray header files (base module) #include "base/povassert.h" @@ -499,7 +497,7 @@ class NumberSequenceFactory GeneratorPtr master; SequenceConstPtr masterSequence; #if POV_MULTITHREADED - boost::mutex masterMutex; + std::mutex masterMutex; #endif }; @@ -527,7 +525,7 @@ class NumberSequenceMetaFactory static FactoryTable* lookupTable; #if POV_MULTITHREADED - static boost::mutex lookupMutex; + static std::mutex lookupMutex; #endif }; @@ -774,7 +772,7 @@ template shared_ptr const> NumberSequenceFactory::operator()(size_t count) { #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(masterMutex); + std::lock_guard lock(masterMutex); #endif if (!masterSequence) { @@ -817,14 +815,14 @@ std::map -boost::mutex NumberSequenceMetaFactory::lookupMutex; +std::mutex NumberSequenceMetaFactory::lookupMutex; #endif template shared_ptr> NumberSequenceMetaFactory::GetFactory(const typename GeneratorType::ParameterStruct& param) { #if POV_MULTITHREADED - boost::mutex::scoped_lock lock(lookupMutex); + std::lock_guard lock(lookupMutex); #endif if (!lookupTable) lookupTable = new FactoryTable(); diff --git a/source/core/math/randomsequence.h b/source/core/math/randomsequence.h index 65af6da16..593725a17 100644 --- a/source/core/math/randomsequence.h +++ b/source/core/math/randomsequence.h @@ -38,6 +38,7 @@ // Module config header file must be the first file included within POV-Ray unit header files #include "core/configcore.h" +#include "core/math/randomsequence_fwd.h" // C++ variants of C standard header files // (none at the moment) diff --git a/source/core/math/randomsequence_fwd.h b/source/core/math/randomsequence_fwd.h new file mode 100644 index 000000000..7f7302a25 --- /dev/null +++ b/source/core/math/randomsequence_fwd.h @@ -0,0 +1,74 @@ +//****************************************************************************** +/// +/// @file core/math/randomsequence_fwd.h +/// +/// Forward declarations related to ... what? +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +#ifndef POVRAY_CORE_RANDOMSEQUENCE_FWD_H +#define POVRAY_CORE_RANDOMSEQUENCE_FWD_H + +/// @file +/// @note +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). + +// C++ standard header files +#include + +// POV-Ray header files (core module) +#include "core/math/vector_fwd.h" + +namespace pov +{ + +template class SequentialNumberGenerator; +using SequentialIntGeneratorPtr = std::shared_ptr>; +using SequentialDoubleGeneratorPtr = std::shared_ptr>; +using SequentialVectorGeneratorPtr = std::shared_ptr>; +using SequentialVector2dGeneratorPtr = std::shared_ptr>; + +template class SeedableNumberGenerator; +using SeedableIntGeneratorPtr = std::shared_ptr>; +using SeedableDoubleGeneratorPtr = std::shared_ptr>; +using SeedableVectorGeneratorPtr = std::shared_ptr>; +using SeedableVector2dGeneratorPtr = std::shared_ptr>; + +template class IndexedNumberGenerator; +using IndexedIntGeneratorPtr = std::shared_ptr const>; +using IndexedDoubleGeneratorPtr = std::shared_ptr const>; +using IndexedVectorGeneratorPtr = std::shared_ptr const>; +using IndexedVector2dGeneratorPtr = std::shared_ptr const>; + +} +// end of namespace pov + +#endif // POVRAY_CORE_RANDOMSEQUENCE_FWD_H diff --git a/source/core/math/vector.h b/source/core/math/vector.h index 174868bf7..8fafee883 100644 --- a/source/core/math/vector.h +++ b/source/core/math/vector.h @@ -38,6 +38,7 @@ // Module config header file must be the first file included within POV-Ray unit header files #include "core/configcore.h" +#include "core/math/vector_fwd.h" // C++ variants of C standard header files // (none at the moment) diff --git a/source/core/math/vector_fwd.h b/source/core/math/vector_fwd.h new file mode 100644 index 000000000..db65361c4 --- /dev/null +++ b/source/core/math/vector_fwd.h @@ -0,0 +1,60 @@ +//****************************************************************************** +/// +/// @file core/math/vector_fwd.h +/// +/// Forward declarations related to vector arithmetics. +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +#ifndef POVRAY_CORE_VECTOR_FWD_H +#define POVRAY_CORE_VECTOR_FWD_H + +/// @file +/// @note +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). + +namespace pov +{ + +template class GenericVector2d; +template class GenericVector3d; + +using Vector2d = GenericVector2d; ///< Double-precision 2D vector. +using SnglVector2d = GenericVector2d; ///< Single-precision 2D vector. + +using Vector3d = GenericVector3d; ///< Double-precision 3D vector. +using SnglVector3d = GenericVector3d; ///< Single-precision 3D vector. +using IntVector3d = GenericVector3d; ///< Integer 3D vector. + +} +// end of namespace pov + +#endif // POVRAY_CORE_VECTOR_FWD_H diff --git a/source/core/precomp.h b/source/core/precomp.h index 35f6028c6..08397dcce 100644 --- a/source/core/precomp.h +++ b/source/core/precomp.h @@ -59,7 +59,6 @@ // C++ standard header files #include -#include #include #include #include @@ -68,17 +67,8 @@ #include #include #include +#include #include // Boost header files -#include -#include -#include -#include #include -#if POV_MULTITHREADED -#include -#include -#endif -#include - diff --git a/source/core/render/trace.cpp b/source/core/render/trace.cpp index 468dd2c49..eb48d4f27 100644 --- a/source/core/render/trace.cpp +++ b/source/core/render/trace.cpp @@ -42,9 +42,6 @@ // C++ standard header files #include -// Boost header files -#include - // POV-Ray header files (base module) #include "base/povassert.h" @@ -69,6 +66,7 @@ #include "core/shape/box.h" #include "core/shape/csg.h" #include "core/support/imageutil.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/render/tracepixel.cpp b/source/core/render/tracepixel.cpp index 32a8abcba..cf8d64a88 100644 --- a/source/core/render/tracepixel.cpp +++ b/source/core/render/tracepixel.cpp @@ -42,7 +42,7 @@ #include "core/render/tracepixel.h" // C++ variants of C standard header files -// (none at the moment) +#include // C++ standard header files #include @@ -74,7 +74,7 @@ using std::max; #ifdef DYNAMIC_HASHTABLE extern unsigned short *hashTable; // GLOBAL VARIABLE #else -extern ALIGN16 unsigned short hashTable[]; // GLOBAL VARIABLE +alignas(16) extern unsigned short hashTable[]; // GLOBAL VARIABLE #endif const int Grid1Size = 4; @@ -1251,7 +1251,7 @@ TracePixel::FocalBlurData::FocalBlurData(const Camera& camera, TraceThreadData* // Allocate temporary grid. std::unique_ptr Grid_Data (new char [Grid_Size * Grid_Size]); char *p = Grid_Data.get(); - memset(p, 0, Grid_Size * Grid_Size); + std::memset(p, 0, Grid_Size * Grid_Size); std::vector Grid(Grid_Size); for(int i = 0; i < Grid_Size; i++, p += Grid_Size) Grid[i] = p; diff --git a/source/core/scene/object.cpp b/source/core/scene/object.cpp index 55a74be24..7cb81c84d 100644 --- a/source/core/scene/object.cpp +++ b/source/core/scene/object.cpp @@ -54,6 +54,7 @@ #include "core/shape/box.h" #include "core/shape/csg.h" #include "core/shape/sphere.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/scene/scenedata.cpp b/source/core/scene/scenedata.cpp index 2b93c3edf..13ae568cd 100644 --- a/source/core/scene/scenedata.cpp +++ b/source/core/scene/scenedata.cpp @@ -42,9 +42,6 @@ // C++ standard header files #include -// Boost header files -#include - // POV-Ray header files (base module) #include "base/types.h" #include "base/version_info.h" diff --git a/source/core/scene/scenedata.h b/source/core/scene/scenedata.h index b93f77fee..ab2da21a9 100644 --- a/source/core/scene/scenedata.h +++ b/source/core/scene/scenedata.h @@ -38,6 +38,7 @@ // Module config header file must be the first file included within POV-Ray unit header files #include "core/configcore.h" +#include "core/scene/scenedata_fwd.h" // C++ variants of C standard header files // (none at the moment) diff --git a/source/core/scene/scenedata_fwd.h b/source/core/scene/scenedata_fwd.h new file mode 100644 index 000000000..a36cb1392 --- /dev/null +++ b/source/core/scene/scenedata_fwd.h @@ -0,0 +1,51 @@ +//****************************************************************************** +/// +/// @file core/scene/scenedata_fwd.h +/// +/// Forward declarations related to ... what? +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +#ifndef POVRAY_CORE_SCENEDATA_FWD_H +#define POVRAY_CORE_SCENEDATA_FWD_H + +/// @file +/// @note +/// This file should not pull in any POV-Ray header whatsoever. + +namespace pov +{ + +class SceneData; + +} +// end of namespace pov + +#endif // POVRAY_CORE_SCENEDATA_FWD_H diff --git a/source/core/scene/tracethreaddata.cpp b/source/core/scene/tracethreaddata.cpp index 203d87b51..2a0dc567f 100644 --- a/source/core/scene/tracethreaddata.cpp +++ b/source/core/scene/tracethreaddata.cpp @@ -51,6 +51,7 @@ #include "core/shape/blob.h" #include "core/shape/fractal.h" #include "core/shape/isosurface.h" +#include "core/support/cracklecache.h" // this must be the last file included #include "base/povdebug.h" @@ -62,7 +63,9 @@ TraceThreadData::TraceThreadData(std::shared_ptr sd, size_t seed) : sceneData(sd), qualityFlags(9), stochasticRandomGenerator(GetRandomDoubleGenerator(0.0,1.0)), - stochasticRandomSeedBase(seed) + stochasticRandomSeedBase(seed), + mpCrackleCache(new CrackleCache), + mpRenderStats(new RenderStatistics) { for(int i = 0; i < 4; i++) Fractal_IStack[i] = nullptr; @@ -114,14 +117,6 @@ TraceThreadData::TraceThreadData(std::shared_ptr sd, size_t seed) : surfacePhotonMap = new PhotonMap(); mediaPhotonMap = new PhotonMap(); - // advise the crackle cache's unordered_map that we don't mind hash collisions - // while this is a very high load factor, the simple fact is that the cost of - // allocating memory at render time (each insert into the table requires an alloc - // as the container doesn't pre-emptively allocate, unlike e.g. std::vector) is - // quite high, particularly when we have multiple threads contending for the heap - // lock. - mCrackleCache.max_load_factor(50.0); - numberOfWaves = sd->numberOfWaves; Initialize_Waves(waveFrequencies, waveSources, numberOfWaves); } @@ -140,43 +135,13 @@ TraceThreadData::~TraceThreadData() delete[] Blob_Intervals; for(std::vector::iterator it = lightSources.begin(); it != lightSources.end(); it++) Destroy_Object(*it); + delete mpCrackleCache; + delete mpRenderStats; } void TraceThreadData::AfterTile() { - CrackleCache::iterator it; - - // this serves as a render block index - progress_index++; - - // probably we ought to have a means for the end-user to choose the preferred maximum bytes reserved for the cache - // for now, we have hard-coded values. we also do not discard any entries that are from the current block, even if - // the cache size is exceeded. also, note that the cache size is per-thread. finally, don't forget that erasing - // elements doesn't in and of itself return the freed memory to the heap. - if (mCrackleCache.size() * sizeof(CrackleCache::value_type) < 15 * 1024 * 1024) - return; - while (mCrackleCache.size() * sizeof(CrackleCache::value_type) > 10 * 1024 * 1024) - { - // search the cache for the oldest entries - int oldest = std::numeric_limits::max(); - for (it = mCrackleCache.begin(); it != mCrackleCache.end(); it++) - if (it->second.lastUsed < oldest) - oldest = (int) it->second.lastUsed; - - // don't remove any entries from the most recent block - if (oldest == progress_index - 1) - break; - - for (it = mCrackleCache.begin(); it != mCrackleCache.end(); ) - { - if (it->second.lastUsed == oldest) - { - it = mCrackleCache.erase(it); - continue; - } - it++; - } - } + mpCrackleCache->Prune(); } } diff --git a/source/core/scene/tracethreaddata.h b/source/core/scene/tracethreaddata.h index b7c0c76fd..e9d9714b4 100644 --- a/source/core/scene/tracethreaddata.h +++ b/source/core/scene/tracethreaddata.h @@ -49,15 +49,16 @@ // POV-Ray header files (base module) #include "base/types.h" +#include "base/colour.h" // POV-Ray header files (core module) #include "core/coretypes.h" #include "core/bounding/boundingcylinder.h" -#include "core/bounding/bsptree.h" -#include "core/material/pattern.h" -#include "core/math/randomsequence.h" -#include "core/shape/mesh.h" -#include "core/support/statistics.h" +#include "core/math/randomsequence_fwd.h" +#include "core/math/vector.h" +#include "core/scene/scenedata_fwd.h" +#include "core/support/cracklecache_fwd.h" +#include "core/support/statistics_fwd.h" namespace pov { @@ -78,10 +79,6 @@ struct Blob_Interval_Struct; /// Class holding parser thread specific data. class TraceThreadData : public ThreadData { - friend class Scene; - friend class Trace; - friend class View; // TODO FIXME - needed only to access TraceThreadData for CheckCameraHollowObject() - public: /// Create thread local data. @@ -95,10 +92,9 @@ class TraceThreadData : public ThreadData /// Get the statistics. /// @return Reference to statistic counters. - RenderStatistics& Stats(void) { return renderStats; } + RenderStatistics& Stats(void) { return *mpRenderStats; } DBL *Fractal_IStack[4]; - BBoxPriorityQueue Mesh_Queue; void **Blob_Queue; unsigned int Max_Blob_Queue_Size; DBL *Blob_Coefficients; @@ -141,7 +137,7 @@ class TraceThreadData : public ThreadData PhotonMap* surfacePhotonMap; PhotonMap* mediaPhotonMap; - CrackleCache mCrackleCache; + CrackleCache* mpCrackleCache; // data for waves and ripples pattern unsigned int numberOfWaves; @@ -178,7 +174,7 @@ class TraceThreadData : public ThreadData /// scene data std::shared_ptr sceneData; /// render statistics - RenderStatistics renderStats; + RenderStatistics* mpRenderStats; private: diff --git a/source/core/shape/bezier.cpp b/source/core/shape/bezier.cpp index a57f5ddf0..dbabce6fe 100644 --- a/source/core/shape/bezier.cpp +++ b/source/core/shape/bezier.cpp @@ -39,18 +39,20 @@ #include "core/shape/bezier.h" // C++ variants of C standard header files -// (none at the moment) +#include // C++ standard header files #include // POV-Ray header files (base module) #include "base/pov_err.h" +#include "base/pov_mem.h" // POV-Ray header files (core module) #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" @@ -1987,7 +1989,7 @@ ObjectPtr BicubicPatch::Copy() if (Weights != nullptr) { New->Weights = reinterpret_cast(POV_MALLOC( sizeof(BEZIER_WEIGHTS),"bicubic patch" )); - POV_MEMCPY( New->Weights, Weights, sizeof(BEZIER_WEIGHTS) ); + std::memcpy( New->Weights, Weights, sizeof(BEZIER_WEIGHTS) ); } for (i = 0; i < 4; i++) diff --git a/source/core/shape/blob.cpp b/source/core/shape/blob.cpp index 6c11a8490..5850ed575 100644 --- a/source/core/shape/blob.cpp +++ b/source/core/shape/blob.cpp @@ -98,7 +98,7 @@ #include "core/shape/blob.h" // C++ variants of C standard header files -// (none at the moment) +#include // C++ standard header files #include @@ -115,6 +115,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" @@ -600,7 +601,7 @@ bool Blob::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadDat * * Store the points of intersection. Keep track of: whether this is * the start or end point of the hit, which component was pierced -* by the ray, and the point along the ray that the hit occured at. +* by the ray, and the point along the ray that the hit occurred at. * * CHANGES * @@ -608,6 +609,7 @@ bool Blob::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadDat * Sep 1995 : Changed to allow use of memcpy if memmove isn't available. [AED] * Jul 1996 : Changed to use POV_MEMMOVE, which can be memmove or pov_memmove. * Oct 1996 : Changed to avoid unnecessary compares. [DB] +* Feb 2019 : Changed back to use std::memmove again. [CLi] * ******************************************************************************/ @@ -630,7 +632,7 @@ void Blob::insert_hit(const Blob_Element *Element, DBL t0, DBL t1, Blob_Interval * bump the rest and insert it here. */ - POV_MEMMOVE(&intervals[k+1], &intervals[k], (*cnt-k)*sizeof(Blob_Interval_Struct)); + std::memmove(&intervals[k+1], &intervals[k], (*cnt-k)*sizeof(Blob_Interval_Struct)); /* We are entering the component. */ @@ -650,7 +652,7 @@ void Blob::insert_hit(const Blob_Element *Element, DBL t0, DBL t1, Blob_Interval if (k < *cnt) { - POV_MEMMOVE(&intervals[k+1], &intervals[k], (*cnt-k)*sizeof(Blob_Interval_Struct)); + std::memmove(&intervals[k+1], &intervals[k], (*cnt-k)*sizeof(Blob_Interval_Struct)); /* We are exiting the component. */ diff --git a/source/core/shape/box.cpp b/source/core/shape/box.cpp index 6e4e96770..245b920d5 100644 --- a/source/core/shape/box.cpp +++ b/source/core/shape/box.cpp @@ -50,6 +50,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/cone.cpp b/source/core/shape/cone.cpp index f5acc49d0..b0b8b3bf4 100644 --- a/source/core/shape/cone.cpp +++ b/source/core/shape/cone.cpp @@ -50,6 +50,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/csg.cpp b/source/core/shape/csg.cpp index a6e3c15e1..ee75e996a 100644 --- a/source/core/shape/csg.cpp +++ b/source/core/shape/csg.cpp @@ -55,6 +55,7 @@ #include "core/shape/heightfield.h" #include "core/shape/plane.h" #include "core/shape/quadric.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/disc.cpp b/source/core/shape/disc.cpp index fd84c7fec..5fc369ed2 100644 --- a/source/core/shape/disc.cpp +++ b/source/core/shape/disc.cpp @@ -50,6 +50,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/fractal.cpp b/source/core/shape/fractal.cpp index 9601f3ca1..c62602882 100644 --- a/source/core/shape/fractal.cpp +++ b/source/core/shape/fractal.cpp @@ -53,6 +53,7 @@ #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" #include "core/shape/sphere.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/heightfield.cpp b/source/core/shape/heightfield.cpp index a91ec7236..6c3500241 100644 --- a/source/core/shape/heightfield.cpp +++ b/source/core/shape/heightfield.cpp @@ -73,6 +73,7 @@ #include "core/scene/tracethreaddata.h" #include "core/shape/box.h" #include "core/support/imageutil.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/isosurface.cpp b/source/core/shape/isosurface.cpp index 5bd9bc9e0..d0aedb96c 100644 --- a/source/core/shape/isosurface.cpp +++ b/source/core/shape/isosurface.cpp @@ -53,6 +53,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/lathe.cpp b/source/core/shape/lathe.cpp index 9b009ae8b..6f1f2ba56 100644 --- a/source/core/shape/lathe.cpp +++ b/source/core/shape/lathe.cpp @@ -139,6 +139,7 @@ #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" #include "core/shape/torus.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/lemon.cpp b/source/core/shape/lemon.cpp index e3355399b..712fbaadd 100644 --- a/source/core/shape/lemon.cpp +++ b/source/core/shape/lemon.cpp @@ -50,6 +50,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/mesh.cpp b/source/core/shape/mesh.cpp index b8b7540d6..34641e831 100644 --- a/source/core/shape/mesh.cpp +++ b/source/core/shape/mesh.cpp @@ -77,6 +77,7 @@ #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" #include "core/shape/triangle.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" @@ -106,6 +107,8 @@ HASH_TABLE **Mesh::Vertex_Hash_Table; HASH_TABLE **Mesh::Normal_Hash_Table; UV_HASH_TABLE **Mesh::UV_Hash_Table; +thread_local std::unique_ptr Mesh::mtpQueue(new BBoxPriorityQueue()); + /***************************************************************************** * * FUNCTION @@ -1458,7 +1461,7 @@ bool Mesh::intersect_bbox_tree(const BasicRay &ray, const BasicRay &Orig_Ray, DB Rayinfo rayinfo(ray); /* Start with an empty priority queue. */ - Thread->Mesh_Queue.Clear(); + mtpQueue->Clear(); found = false; Best = BOUND_HUGE; @@ -1473,13 +1476,13 @@ bool Mesh::intersect_bbox_tree(const BasicRay &ray, const BasicRay &Orig_Ray, DB /* Set the root object infinite to avoid a test. */ - Check_And_Enqueue(Thread->Mesh_Queue, Root, &Root->BBox, &rayinfo, Thread->Stats()); + Check_And_Enqueue(*mtpQueue, Root, &Root->BBox, &rayinfo, Thread->Stats()); /* Check elements in the priority queue. */ - while (!Thread->Mesh_Queue.IsEmpty()) + while (!mtpQueue->IsEmpty()) { - Thread->Mesh_Queue.RemoveMin(Depth, Node); + mtpQueue->RemoveMin(Depth, Node); /* * If current intersection is larger than the best intersection found @@ -1503,7 +1506,7 @@ bool Mesh::intersect_bbox_tree(const BasicRay &ray, const BasicRay &Orig_Ray, DB /* This is a node containing leaves to be checked. */ for (i = 0; i < Node->Entries; i++) - Check_And_Enqueue(Thread->Mesh_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo, Thread->Stats()); + Check_And_Enqueue(*mtpQueue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo, Thread->Stats()); } else { @@ -2370,7 +2373,7 @@ bool Mesh::inside_bbox_tree(const BasicRay &ray, TraceThreadData *Thread) const Rayinfo rayinfo(ray); /* Start with an empty priority queue. */ - Thread->Mesh_Queue.Clear(); + mtpQueue->Clear(); found = 0; Best = BOUND_HUGE; @@ -2383,19 +2386,19 @@ bool Mesh::inside_bbox_tree(const BasicRay &ray, TraceThreadData *Thread) const Root = Data->Tree; /* Set the root object infinite to avoid a test. */ - Check_And_Enqueue(Thread->Mesh_Queue, Root, &Root->BBox, &rayinfo, Thread->Stats()); + Check_And_Enqueue(*mtpQueue, Root, &Root->BBox, &rayinfo, Thread->Stats()); /* Check elements in the priority queue. */ - while (!Thread->Mesh_Queue.IsEmpty()) + while (!mtpQueue->IsEmpty()) { - Thread->Mesh_Queue.RemoveMin(Depth, Node); + mtpQueue->RemoveMin(Depth, Node); /* Check current node. */ if (Node->Entries) { /* This is a node containing leaves to be checked. */ for (i = 0; i < Node->Entries; i++) - Check_And_Enqueue(Thread->Mesh_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo, Thread->Stats()); + Check_And_Enqueue(*mtpQueue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo, Thread->Stats()); } else { diff --git a/source/core/shape/mesh.h b/source/core/shape/mesh.h index f6493e138..4a75843f0 100644 --- a/source/core/shape/mesh.h +++ b/source/core/shape/mesh.h @@ -40,9 +40,11 @@ #include "core/configcore.h" // C++ variants of C standard header files -// C++ standard header files // (none at the moment) +// C++ standard header files +#include + // POV-Ray header files (base module) // (none at the moment) @@ -194,6 +196,17 @@ class Mesh final : public ObjectBase static HASH_TABLE **Vertex_Hash_Table; static HASH_TABLE **Normal_Hash_Table; static UV_HASH_TABLE **UV_Hash_Table; + + /// Priority queue object. + /// + /// This object is for temporary use in the intersection and insideness tests; + /// the only reason it is not simply a local variable there is that we want to + /// avoid the overhead of repeated construction and destruction on the stack. + /// Technically we could get the same performance by keeping it local to the + /// functions and making it thread-local, but this would mean having one such + /// object per function, when it's perfectly safe for them to share one object. + /// + static thread_local std::unique_ptr mtpQueue; }; /// @} diff --git a/source/core/shape/ovus.cpp b/source/core/shape/ovus.cpp index f42e461b5..ffec245a4 100644 --- a/source/core/shape/ovus.cpp +++ b/source/core/shape/ovus.cpp @@ -81,6 +81,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/parametric.cpp b/source/core/shape/parametric.cpp index 065dd5c82..f815d7a07 100644 --- a/source/core/shape/parametric.cpp +++ b/source/core/shape/parametric.cpp @@ -50,6 +50,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/plane.cpp b/source/core/shape/plane.cpp index f1f3c2f03..376d92c27 100644 --- a/source/core/shape/plane.cpp +++ b/source/core/shape/plane.cpp @@ -47,6 +47,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/polygon.cpp b/source/core/shape/polygon.cpp index 5aef6ba8e..5964bc52b 100644 --- a/source/core/shape/polygon.cpp +++ b/source/core/shape/polygon.cpp @@ -74,6 +74,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/polynomial.cpp b/source/core/shape/polynomial.cpp index de466ca24..2f82214e3 100644 --- a/source/core/shape/polynomial.cpp +++ b/source/core/shape/polynomial.cpp @@ -51,6 +51,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/prism.cpp b/source/core/shape/prism.cpp index 381a83200..274c4a2bb 100644 --- a/source/core/shape/prism.cpp +++ b/source/core/shape/prism.cpp @@ -130,6 +130,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/quadric.cpp b/source/core/shape/quadric.cpp index a2f1146e6..48898f88d 100644 --- a/source/core/shape/quadric.cpp +++ b/source/core/shape/quadric.cpp @@ -52,6 +52,7 @@ #include "core/render/ray.h" #include "core/shape/plane.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/sor.cpp b/source/core/shape/sor.cpp index 3342ee951..04fc53ccd 100644 --- a/source/core/shape/sor.cpp +++ b/source/core/shape/sor.cpp @@ -115,6 +115,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/sphere.cpp b/source/core/shape/sphere.cpp index e79e01fdb..788cd3a33 100644 --- a/source/core/shape/sphere.cpp +++ b/source/core/shape/sphere.cpp @@ -48,6 +48,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/spheresweep.cpp b/source/core/shape/spheresweep.cpp index 13d6d1412..03c8f929f 100644 --- a/source/core/shape/spheresweep.cpp +++ b/source/core/shape/spheresweep.cpp @@ -96,6 +96,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/superellipsoid.cpp b/source/core/shape/superellipsoid.cpp index d1d94ddc2..f2afc5eb2 100644 --- a/source/core/shape/superellipsoid.cpp +++ b/source/core/shape/superellipsoid.cpp @@ -80,6 +80,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/torus.cpp b/source/core/shape/torus.cpp index 4a084ee88..e881d2bd8 100644 --- a/source/core/shape/torus.cpp +++ b/source/core/shape/torus.cpp @@ -61,6 +61,7 @@ #include "core/math/polynomialsolver.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/triangle.cpp b/source/core/shape/triangle.cpp index be771c7a2..c5a801a0f 100644 --- a/source/core/shape/triangle.cpp +++ b/source/core/shape/triangle.cpp @@ -47,6 +47,7 @@ #include "core/math/matrix.h" #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/shape/truetype.cpp b/source/core/shape/truetype.cpp index bd225c33c..50dd3218e 100644 --- a/source/core/shape/truetype.cpp +++ b/source/core/shape/truetype.cpp @@ -56,6 +56,7 @@ #include "core/render/ray.h" #include "core/scene/tracethreaddata.h" #include "core/shape/csg.h" +#include "core/support/statistics.h" // this must be the last file included #include "base/povdebug.h" diff --git a/source/core/support/cracklecache.cpp b/source/core/support/cracklecache.cpp new file mode 100644 index 000000000..4f897d18a --- /dev/null +++ b/source/core/support/cracklecache.cpp @@ -0,0 +1,151 @@ +//****************************************************************************** +/// +/// @file core/support/cracklecache.cpp +/// +/// Implementation of the crackle pattern cache. +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +// Unit header file must be the first file included within POV-Ray *.cpp files (pulls in config) +#include "core/support/cracklecache.h" + +// C++ variants of C standard header files +// C++ standard header files +// (none at the moment) + +// POV-Ray header files (base module) +// POV-Ray header files (core module) +// POV-Ray header files (parser module) +// (none at the moment) + +// this must be the last file included +#include "base/povdebug.h" + +namespace pov +{ + +CrackleCache::CrackleCache() : + mPruneCounter(0) +{ + // Advise the unordered_map that we don't mind hash collisions. + // While this is a very high load factor, the simple fact is that the cost of + // allocating memory at render time (each insert into the table requires an alloc + // as the container doesn't pre-emptively allocate, unlike e.g. std::vector) is + // quite high, particularly when we have multiple threads contending for the heap + // lock. + mData.max_load_factor(50.0); +} + +bool CrackleCache::Lookup(CrackleCacheEntryPtr& entry, const CrackleCellCoord& coord) +{ + // search for this hash value in the cache + CrackleCacheData::iterator iter = mData.find(coord); + bool found = (iter != mData.end()); + + if (!found) + { + // Not in cache. + + // If cache is already excessively large; refrain from creating a new entry. + // Having to re-calculate entries that would have been cache hits had we not + // skipped on adding an entry is less expensive than chewing up immense amounts + // of RAM and finally hitting the swapfile. unfortunately there's no good way + // to tell how much memory is 'too much' for the cache, so we just use a hard- + // coded number for now (ideally we should allow the user to configure this). + // keep in mind that the cache memory usage is per-thread, so the more threads, + // the more RAM. If we don't do the insert, `entry` will remain unchanged. + if (mData.size() * sizeof(CrackleCacheData::value_type) >= 30 * 1024 * 1024) + return false; + + // Generate a new cache entry. + iter = mData.insert(mData.end(), CrackleCacheData::value_type(coord, CrackleCacheEntry())); + entry = &iter->second; + entry->lastUsed = mPruneCounter; + return false; + } + else + { + entry = &iter->second; + // NB: We're deliberately _not_ updating `entry->lastUsed` here, as that + // seems to be counter-productive to performance. + return true; + } +} + +void CrackleCache::Prune() +{ + CrackleCacheData::iterator it; + + // This serves as a kind of "clock" to track age of cache entries. + ++mPruneCounter; + + // Probably we ought to have a means for the end-user to choose the preferred maximum bytes reserved for the cache. + // For now, we have hard-coded values. we also do not discard any entries that are from the current block, even if + // the cache size is exceeded. also, note that the cache size is per-thread. finally, don't forget that erasing + // elements doesn't in and of itself return the freed memory to the heap. + + // Don't go through the hassle of pruning unless the cache has reached a certain size. + if (mData.size() * sizeof(CrackleCacheData::value_type) < 15 * 1024 * 1024 / 64) + return; + + // If we're pruning, aim for a somewhat lower size. + // Traverse the map to determine the oldest age, then traverse it again to + // throw away all entries with that age. Rinse, repeat. + // TODO - This salami approach - cutting away one slice at a time - seems + // inefficient; instead, from the oldest age we should probably be + // able to guesstimate a cut-off age that will get us close to the + // desired cache size, and then throw away everything older than + // that in a single pass. + while (mData.size() * sizeof(CrackleCacheData::value_type) > 10 * 1024 * 1024 / 64) + { + // search the cache for the oldest entries + int oldest = std::numeric_limits::max(); + for (it = mData.begin(); it != mData.end(); it++) + if (it->second.lastUsed < oldest) + oldest = (int)it->second.lastUsed; + + // don't remove any entries from the most recent block + if (oldest == mPruneCounter) + break; + + for (it = mData.begin(); it != mData.end(); ) + { + if (it->second.lastUsed == oldest) + { + it = mData.erase(it); + continue; + } + it++; + } + } +} + +} +// end of namespace pov diff --git a/source/core/support/cracklecache.h b/source/core/support/cracklecache.h new file mode 100644 index 000000000..ac424fcd4 --- /dev/null +++ b/source/core/support/cracklecache.h @@ -0,0 +1,169 @@ +//****************************************************************************** +/// +/// @file core/support/cracklecache.h +/// +/// Declarations related to crackle pattern cache. +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +#ifndef POVRAY_CORE_CRACKLECACHE_H +#define POVRAY_CORE_CRACKLECACHE_H + +// Module config header file must be the first file included within POV-Ray unit header files +#include "core/configcore.h" +#include "core/support/cracklecache_fwd.h" + +// C++ variants of C standard header files +// (none at the moment) + +// C++ standard header files +#include + +// Boost header files +#include + +// POV-Ray header files (base module) +#include "base/mathutil.h" + +// POV-Ray header files (core module) +#include "core/math/vector.h" + +namespace pov +{ + +//****************************************************************************** + +/// Helper class to implement the crackle cache. +class CrackleCellCoord final +{ +public: + + CrackleCellCoord() : mX(0), mY(0), mZ(0), mRepeatX(0), mRepeatY(0), mRepeatZ(0) {} + CrackleCellCoord(int x, int y, int z, int rx, int ry, int rz) : mX(x), mY(y), mZ(z), mRepeatX(rx), mRepeatY(ry), mRepeatZ(rz) + { + WrapCellCoordinate(mX, mRepeatX); + WrapCellCoordinate(mY, mRepeatY); + WrapCellCoordinate(mZ, mRepeatZ); + } + + bool operator==(CrackleCellCoord const& other) const + { + return mX == other.mX && mY == other.mY && mZ == other.mZ; + } + + /// Function to compute a hash value from the coordinates. + /// + /// @note This function's name, as well as it being a global function rather than a member, is mandated by + /// std::unordered_map. + /// + /// @param[in] coord The coordinate. + /// @return The hash. + /// + friend std::size_t hash_value(CrackleCellCoord const& coord) + { + std::size_t seed = 0; + boost::hash_combine(seed, coord.mX); + boost::hash_combine(seed, coord.mY); + boost::hash_combine(seed, coord.mZ); + + return seed; + } + +protected: + + int mX; + int mY; + int mZ; + int mRepeatX; + int mRepeatY; + int mRepeatZ; + + static inline void WrapCellCoordinate(int& v, int& repeat) + { + if (!repeat) + return; + v = pov_base::wrapInt(v, repeat); + if ((v >= 2) && (v < repeat - 2)) + repeat = 0; + } +}; + +//****************************************************************************** + +/// Helper class to implement the crackle cache. +struct CrackleCacheEntry final +{ + /// A kind of timestamp specifying when this particular entry was last used. + size_t lastUsed; + + /// The pseudo-random points defining the pattern in this particular subset of 3D space. + Vector3d aCellNuclei[81]; +}; +using CrackleCacheEntryPtr = CrackleCacheEntry*; + +//****************************************************************************** + +/// Crackle cache. +/// +/// This class buffers the pseudorandom "seeds points" for the Voronoi-based +/// crackle pattern. +/// +class CrackleCache final +{ +public: + + /// Construct a new crackle cache. + CrackleCache(); + + /// Look up cache entry. + /// If the queried entry is not currently in the cache, an empty entry is + /// automatically created, unless the cache has reached an excessive size. + /// @param[out] entry Pointer to cache entry, or unchanged if not in cache. + /// @param[in] coord Crackle cell coordinates. + /// @return `true` if entry already existed, `false` otherwise. + bool Lookup(CrackleCacheEntryPtr& entry, const CrackleCellCoord& coord); + + /// Prune the crackle cache. + /// This function is intended to be called at regular intervals to remove + /// the least recently used entries from the cache to keep it reasonably + /// lean and fast. + void Prune(); + +private: + + using CrackleCacheData = std::unordered_map>; + CrackleCacheData mData; + std::size_t mPruneCounter; +}; + +} +// end of namespace pov + +#endif // POVRAY_CORE_CRACKLECACHE_H diff --git a/source/core/support/cracklecache_fwd.h b/source/core/support/cracklecache_fwd.h new file mode 100644 index 000000000..154405028 --- /dev/null +++ b/source/core/support/cracklecache_fwd.h @@ -0,0 +1,55 @@ +//****************************************************************************** +/// +/// @file core/support/cracklecache_fwd.h +/// +/// Forward declarations related to the crackle pattern cache. +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +#ifndef POVRAY_CORE_CRACKLECACHE_FWD_H +#define POVRAY_CORE_CRACKLECACHE_FWD_H + +/// @file +/// @note +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). + +// C++ standard header files +// (none at the moment) + +namespace pov +{ + +class CrackleCache; + +} +// end of namespace pov + +#endif // POVRAY_CORE_CRACKLECACHE_FWD_H diff --git a/source/core/support/octree.cpp b/source/core/support/octree.cpp index c78cd673c..aa7695e12 100644 --- a/source/core/support/octree.cpp +++ b/source/core/support/octree.cpp @@ -61,6 +61,7 @@ #include #include #include +#include // C++ standard header files #include @@ -204,7 +205,7 @@ static inline float Pow2Floor(float a) /// @f] /// /// The value of the bias _b_ depends on @ref POV_PORTABLE_RADIOSITY, bit is -/// the same value as used by @BiasedIntPow2(). +/// the same value as used by @ref BiasedIntPow2(). /// /// @note /// The function signature may differ depending on @@ -231,11 +232,11 @@ static inline int BiasedIntLog2(float a) /// @f] /// /// The value of the bias _b_ depends on @ref POV_PORTABLE_RADIOSITY, bit is -/// the same value as used by @BiasedIntLog2(). +/// the same value as used by @ref BiasedIntLog2(). /// /// @note /// The function signature may differ depending on -/// @ref POV_PORTABLE_BIASEDINTPOW2. +/// @ref POV_PORTABLE_RADIOSITY. /// static inline float BiasedIntPow2(int a) { @@ -1580,7 +1581,7 @@ bool ot_read_file(OT_NODE **root, IStream *fd, const OT_READ_PARAM* param, OT_RE new_block = reinterpret_cast(POV_MALLOC(sizeof (OT_BLOCK), "octree node from file")); if (new_block != nullptr) { - POV_MEMCPY(new_block, &bl, sizeof (OT_BLOCK)); + std::memcpy(new_block, &bl, sizeof (OT_BLOCK)); ot_index_sphere(bl.Point, bl.Harmonic_Mean_Distance * param->RealErrorBound, &id); ot_ins(root, new_block, &id); diff --git a/source/core/support/octree_fwd.h b/source/core/support/octree_fwd.h index 5020b9c14..d85e06c4b 100644 --- a/source/core/support/octree_fwd.h +++ b/source/core/support/octree_fwd.h @@ -36,12 +36,13 @@ #ifndef POVRAY_CORE_OCTREE_FWD_H #define POVRAY_CORE_OCTREE_FWD_H -// C++ standard header files -#include - /// @file /// @note -/// This file should not pull in any POV-Ray header whatsoever. +/// This file should not pull in any headers whatsoever (except other +/// forward declaration headers or certain select standard headers). + +// C++ standard header files +#include namespace pov { diff --git a/source/core/support/statistics.h b/source/core/support/statistics.h index dd076f6f1..4c18cd2fe 100644 --- a/source/core/support/statistics.h +++ b/source/core/support/statistics.h @@ -38,6 +38,7 @@ // Module config header file must be the first file included within POV-Ray unit header files #include "core/configcore.h" +#include "core/support/statistics_fwd.h" // C++ variants of C standard header files #include diff --git a/source/core/support/statistics_fwd.h b/source/core/support/statistics_fwd.h new file mode 100644 index 000000000..dfa278ee6 --- /dev/null +++ b/source/core/support/statistics_fwd.h @@ -0,0 +1,51 @@ +//****************************************************************************** +/// +/// @file core/support/statistics_fwd.h +/// +/// Forward declarations related to ... what? +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +#ifndef POVRAY_CORE_STATISTICS_FWD_H +#define POVRAY_CORE_STATISTICS_FWD_H + +/// @file +/// @note +/// This file should not pull in any POV-Ray header whatsoever. + +namespace pov +{ + +class RenderStatistics; + +} +// end of namespace pov + +#endif // POVRAY_CORE_STATISTICS_FWD_H diff --git a/source/frontend/imagemessagehandler.cpp b/source/frontend/imagemessagehandler.cpp index d99357fee..c260f802f 100644 --- a/source/frontend/imagemessagehandler.cpp +++ b/source/frontend/imagemessagehandler.cpp @@ -45,7 +45,6 @@ // POV-Ray header files (base module) #include "base/fileinputoutput.h" #include "base/types.h" -#include "base/image/colourspace.h" #include "base/image/dither.h" #include "base/image/encoding.h" #include "base/image/image.h" diff --git a/source/frontend/parsermessagehandler.cpp b/source/frontend/parsermessagehandler.cpp index 5cdcdf304..322a589e5 100644 --- a/source/frontend/parsermessagehandler.cpp +++ b/source/frontend/parsermessagehandler.cpp @@ -40,6 +40,7 @@ // (none at the moment) // C++ standard header files +#include #include // POV-Ray header files (base module) diff --git a/source/frontend/precomp.h b/source/frontend/precomp.h index 70db91f1e..74acf21ca 100644 --- a/source/frontend/precomp.h +++ b/source/frontend/precomp.h @@ -59,7 +59,6 @@ // C++ standard header files #include -#include #include #include #include @@ -71,13 +70,4 @@ #include // Boost header files -#include #include -#include -#include -#if POV_MULTITHREADED -#include -#include -#endif -#include - diff --git a/source/frontend/processrenderoptions.cpp b/source/frontend/processrenderoptions.cpp index 818633d54..e257dbc90 100644 --- a/source/frontend/processrenderoptions.cpp +++ b/source/frontend/processrenderoptions.cpp @@ -48,7 +48,6 @@ #include "base/stringutilities.h" #include "base/image/colourspace.h" #include "base/image/dither.h" -#include "base/image/encoding.h" // POV-Ray header files (core module) #include "base/fileinputoutput.h" diff --git a/source/frontend/renderfrontend.cpp b/source/frontend/renderfrontend.cpp index f0cb9c2d2..6827d9219 100644 --- a/source/frontend/renderfrontend.cpp +++ b/source/frontend/renderfrontend.cpp @@ -44,13 +44,13 @@ // POV-Ray header files (base module) #include "base/fileinputoutput.h" +#include "base/mathutil.h" #include "base/platformbase.h" #include "base/textstream.h" #include "base/textstreambuffer.h" #include "base/types.h" #include "base/image/colourspace.h" #include "base/image/dither.h" -#include "base/image/encoding.h" // POV-Ray header files (POVMS module) #include "povms/povmsid.h" diff --git a/source/frontend/renderfrontend.h b/source/frontend/renderfrontend.h index efcabd6cb..fb83956e1 100644 --- a/source/frontend/renderfrontend.h +++ b/source/frontend/renderfrontend.h @@ -51,6 +51,9 @@ #include #include +// Boost header files +#include + // POV-Ray header files (base module) #include "base/fileinputoutput.h" #include "base/filesystem.h" diff --git a/source/frontend/rendermessagehandler.cpp b/source/frontend/rendermessagehandler.cpp index 3437853b2..374823dab 100644 --- a/source/frontend/rendermessagehandler.cpp +++ b/source/frontend/rendermessagehandler.cpp @@ -37,9 +37,11 @@ #include "frontend/rendermessagehandler.h" // C++ variants of C standard header files -// C++ standard header files // (none at the moment) +// C++ standard header files +#include + // POV-Ray header files (base module) // POV-Ray header files (POVMS module) // (none at the moment) diff --git a/source/frontend/shelloutprocessing.cpp b/source/frontend/shelloutprocessing.cpp index 5e11f9076..c5b2aa0b9 100644 --- a/source/frontend/shelloutprocessing.cpp +++ b/source/frontend/shelloutprocessing.cpp @@ -41,7 +41,6 @@ // (none at the moment) // Boost header files -#include #include // POV-Ray header files (base module) diff --git a/source/frontend/simplefrontend.h b/source/frontend/simplefrontend.h index e6fc7a3f8..9cdbfc82e 100644 --- a/source/frontend/simplefrontend.h +++ b/source/frontend/simplefrontend.h @@ -45,6 +45,9 @@ // C++ standard header files #include +// Boost header files +#include + // POV-Ray header files (base module) #include "base/povassert.h" #include "base/stringutilities.h" diff --git a/source/parser/fncode.cpp b/source/parser/fncode.cpp index 41fe13e26..0fddf587b 100644 --- a/source/parser/fncode.cpp +++ b/source/parser/fncode.cpp @@ -393,7 +393,7 @@ void FNCode_Copy(FunctionCode *f, FunctionCode *fnew) if (f->program != nullptr) { fnew->program = reinterpret_cast(POV_MALLOC(sizeof(Instruction) * f->program_size, "fn: program")); - POV_MEMCPY(fnew->program, f->program, sizeof(Instruction) * f->program_size); + std::memcpy(fnew->program, f->program, sizeof(Instruction) * f->program_size); } if (f->name != nullptr) { diff --git a/source/parser/parser.cpp b/source/parser/parser.cpp index 27e4c0c36..5ecd39536 100644 --- a/source/parser/parser.cpp +++ b/source/parser/parser.cpp @@ -42,13 +42,11 @@ #include #include #include +#include // C++ standard header files #include -// Boost header files -#include - // POV-Ray header files (base module) #include "base/fileinputoutput.h" #include "base/fileutil.h" @@ -71,6 +69,7 @@ #include "core/material/interior.h" #include "core/material/noise.h" #include "core/material/normal.h" +#include "core/material/pattern.h" #include "core/material/pigment.h" #include "core/material/texture.h" #include "core/math/matrix.h" @@ -157,6 +156,18 @@ Parser::Parser(shared_ptr sd, const Options& opts, mTokensSinceLastProgressReport(0), next_rand(nullptr) { + std::tm tmY2K; + // Field = Value - Base + tmY2K.tm_year = 2000 - 1900; + tmY2K.tm_mon = 1 - 1; + tmY2K.tm_mday = 1 - 0; + tmY2K.tm_hour = 0; + tmY2K.tm_min = 0; + tmY2K.tm_sec = 0; + tmY2K.tm_isdst = false; + // `std::mktime()` doesn't need `tmY2K.tm_wday` nor `tmY2K.yday` to be set. + mY2K = std::chrono::system_clock::from_time_t(std::mktime(&tmY2K)); + pre_init_tokenizer(); if (sceneData->realTimeRaytracing) mBetaFeatureFlags.realTimeRaytracing = true; diff --git a/source/parser/parser.h b/source/parser/parser.h index 1353e9ff6..aa0b62f74 100644 --- a/source/parser/parser.h +++ b/source/parser/parser.h @@ -46,6 +46,7 @@ // (none at the moment) // C++ standard header files +#include #include #include #include @@ -734,6 +735,8 @@ class Parser final size_t MaxCachedMacroSize; + std::chrono::system_clock::time_point mY2K; + // parse.h/parse.cpp void Frame_Init(void); void InitDefaults(int version); diff --git a/source/parser/parser_expressions.cpp b/source/parser/parser_expressions.cpp index 357c7e3f6..cce741027 100644 --- a/source/parser/parser_expressions.cpp +++ b/source/parser/parser_expressions.cpp @@ -40,12 +40,11 @@ #include #include #include +#include // C++ standard header files #include - -// Boost header files -#include +#include // POV-Ray header files (base module) #include "base/fileinputoutput.h" @@ -975,9 +974,9 @@ void Parser::Parse_Num_Factor (EXPRESS& Express,int *Terms) case NOW_TOKEN: { - static boost::posix_time::ptime y2k(boost::gregorian::date(2000,1,1)); - boost::posix_time::ptime now(boost::posix_time::microsec_clock::universal_time()); - Val = (now-y2k).total_microseconds() * (1.0e-6) / (24*60*60); + auto now = std::chrono::system_clock::now(); + using FractionalDays = std::chrono::duration>; + Val = std::chrono::duration_cast (now - mY2K).count(); } break; } @@ -1723,7 +1722,7 @@ void Parser::Parse_Express (EXPRESS& Express,int *Terms) Chosen = &Local_Express2; *Terms = Local_Terms2; } - POV_MEMCPY(Express, Chosen, sizeof(EXPRESS)); + std::memcpy(Express, Chosen, sizeof(EXPRESS)); } else { diff --git a/source/parser/parser_strings.cpp b/source/parser/parser_strings.cpp index 89c128421..33508ee62 100644 --- a/source/parser/parser_strings.cpp +++ b/source/parser/parser_strings.cpp @@ -40,6 +40,7 @@ #include #include #include +#include // C++ standard header files // (none at the moment) @@ -145,7 +146,7 @@ UCS2 *Parser::Parse_String(bool pathname, bool require) len = pString->size() + 1; New = reinterpret_cast(POV_MALLOC(len * sizeof(UCS2), "UCS2 String")); - POV_MEMCPY(reinterpret_cast(New), + std::memcpy(reinterpret_cast(New), reinterpret_cast(pString->c_str()), len * sizeof(UCS2)); EXIT @@ -194,7 +195,7 @@ UCS2 *Parser::Parse_String(bool pathname, bool require) CASE(STRING_ID_TOKEN) len = UCS2_strlen(CurrentTokenDataPtr()) + 1; New = reinterpret_cast(POV_MALLOC(len * sizeof(UCS2), "UCS2 String")); - POV_MEMCPY(reinterpret_cast(New), CurrentTokenDataPtr(), len * sizeof(UCS2)); + std::memcpy(reinterpret_cast(New), CurrentTokenDataPtr(), len * sizeof(UCS2)); EXIT END_CASE diff --git a/source/parser/parsertypes.cpp b/source/parser/parsertypes.cpp index 5bdc6aa18..c870a8f29 100644 --- a/source/parser/parsertypes.cpp +++ b/source/parser/parsertypes.cpp @@ -38,8 +38,6 @@ // C++ variants of C standard header files // C++ standard header files -// Boost header files -// (none at the moment) // POV-Ray header files (base module) #include "base/fileinputoutput.h" diff --git a/source/parser/parsertypes.h b/source/parser/parsertypes.h index 4fcf84a17..8f0f7cf58 100644 --- a/source/parser/parsertypes.h +++ b/source/parser/parsertypes.h @@ -45,9 +45,6 @@ // C++ standard header files #include -// Boost header files -// (none at the moment) - // POV-Ray header files (base module) #include "base/fileinputoutput_fwd.h" #include "base/messenger.h" diff --git a/source/parser/precomp.h b/source/parser/precomp.h index a8f5d0853..308d36038 100644 --- a/source/parser/precomp.h +++ b/source/parser/precomp.h @@ -59,7 +59,7 @@ // C++ standard header files #include -#include +#include #include #include #include @@ -68,17 +68,8 @@ #include #include #include +#include #include // Boost header files -#include -#include -#include -#include #include -#if POV_MULTITHREADED -#include -#include -#endif -#include - diff --git a/source/parser/rawtokenizer.cpp b/source/parser/rawtokenizer.cpp index 64040782f..d1336d9be 100644 --- a/source/parser/rawtokenizer.cpp +++ b/source/parser/rawtokenizer.cpp @@ -38,8 +38,6 @@ // C++ variants of C standard header files // C++ standard header files -// Boost header files -// (none at the moment) // POV-Ray header files (base module) #include "base/fileinputoutput.h" diff --git a/source/parser/rawtokenizer.h b/source/parser/rawtokenizer.h index 80bece576..92be183c2 100644 --- a/source/parser/rawtokenizer.h +++ b/source/parser/rawtokenizer.h @@ -46,9 +46,6 @@ #include #include -// Boost header files -// (none at the moment) - // POV-Ray header files (base module) #include "base/stringtypes.h" diff --git a/source/parser/scanner.cpp b/source/parser/scanner.cpp index 885c55fb9..9f5d6e4a4 100644 --- a/source/parser/scanner.cpp +++ b/source/parser/scanner.cpp @@ -45,9 +45,6 @@ #include #include -// Boost header files -// (none at the moment) - // POV-Ray header files (base module) #include "base/fileinputoutput.h" #include "base/povassert.h" diff --git a/source/parser/scanner.h b/source/parser/scanner.h index 68365cd32..67df35d25 100644 --- a/source/parser/scanner.h +++ b/source/parser/scanner.h @@ -46,9 +46,6 @@ #include #include -// Boost header files -// (none at the moment) - // POV-Ray header files (base module) #include "base/messenger_fwd.h" #include "base/stringtypes.h" diff --git a/source/parser/symboltable.cpp b/source/parser/symboltable.cpp index 071c7acf3..d028a54ff 100644 --- a/source/parser/symboltable.cpp +++ b/source/parser/symboltable.cpp @@ -37,8 +37,9 @@ #include "parser/symboltable.h" // C++ variants of C standard header files +#include + // C++ standard header files -// Boost header files // (none at the moment) // POV-Ray header files (base module) @@ -265,7 +266,7 @@ void* SymbolTable::Copy_Identifier(void* Data, int Type) case STRING_ID_TOKEN: len = UCS2_strlen(reinterpret_cast(Data)) + 1; New = reinterpret_cast(POV_MALLOC(len * sizeof(UCS2), "UCS2 String")); - POV_MEMCPY(reinterpret_cast(New), reinterpret_cast(Data), len * sizeof(UCS2)); + std::memcpy(reinterpret_cast(New), reinterpret_cast(Data), len * sizeof(UCS2)); break; case ARRAY_ID_TOKEN: New = CloneData(Data); diff --git a/source/parser/symboltable.h b/source/parser/symboltable.h index de34cbb23..52da82502 100644 --- a/source/parser/symboltable.h +++ b/source/parser/symboltable.h @@ -45,9 +45,6 @@ // C++ standard header files #include -// Boost header files -// (none at the moment) - // POV-Ray header files (base module) #include "base/stringtypes.h" diff --git a/source/povmain.cpp b/source/povmain.cpp index 3f296b697..e90e5080f 100644 --- a/source/povmain.cpp +++ b/source/povmain.cpp @@ -33,7 +33,6 @@ /// //****************************************************************************** -#include #include #include diff --git a/source/povms/precomp.h b/source/povms/precomp.h index 9ad2a0b3e..0f82796d8 100644 --- a/source/povms/precomp.h +++ b/source/povms/precomp.h @@ -59,7 +59,6 @@ // C++ standard header files #include -#include #include #include #include @@ -69,14 +68,3 @@ #include #include #include - -// Boost header files -#include -#include -#include -#include -#if POV_MULTITHREADED -#include -#include -#endif -#include diff --git a/source/vm/fnintern.cpp b/source/vm/fnintern.cpp index c09c84cc2..94bd28f3f 100644 --- a/source/vm/fnintern.cpp +++ b/source/vm/fnintern.cpp @@ -51,6 +51,7 @@ // POV-Ray header files (core module) #include "core/material/noise.h" +#include "core/material/pattern.h" #include "core/material/pigment.h" #include "core/material/warp.h" #include "core/math/matrix.h" diff --git a/source/vm/fnpovfpu.cpp b/source/vm/fnpovfpu.cpp index 3cfd68789..c302558d4 100644 --- a/source/vm/fnpovfpu.cpp +++ b/source/vm/fnpovfpu.cpp @@ -246,6 +246,7 @@ Density of instruction set: 916 / 1024 = 0.8945 // POV-Ray header files (core module) #include "core/scene/tracethreaddata.h" +#include "core/support/statistics.h" // POV-Ray header files (VM module) #include "vm/fnintern.h" diff --git a/source/vm/precomp.h b/source/vm/precomp.h index 46e5b0738..1f1a046ee 100644 --- a/source/vm/precomp.h +++ b/source/vm/precomp.h @@ -59,7 +59,6 @@ // C++ standard header files #include -#include #include #include #include @@ -71,14 +70,4 @@ #include // Boost header files -#include -#include -#include -#include #include -#if POV_MULTITHREADED -#include -#include -#endif -#include - diff --git a/tests/source/tests.h b/tests/source/tests.h index 873d4c7a0..a13c9a5c2 100644 --- a/tests/source/tests.h +++ b/tests/source/tests.h @@ -8,7 +8,7 @@ /// @parblock /// /// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. -/// Copyright 1991-2017 Persistence of Vision Raytracer Pty. Ltd. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. /// /// POV-Ray is free software: you can redistribute it and/or modify /// it under the terms of the GNU Affero General Public License as @@ -38,4 +38,6 @@ #include +#include "base/povassert.h" + #endif // POVRAY_TESTS_H diff --git a/tools/doxygen/doxygen.cfg b/tools/doxygen/doxygen.cfg index e881467ae..36dfb74cb 100644 --- a/tools/doxygen/doxygen.cfg +++ b/tools/doxygen/doxygen.cfg @@ -426,7 +426,7 @@ EXTRACT_ALL = NO # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. @@ -438,7 +438,7 @@ EXTRACT_PACKAGE = NO # included in the documentation. # The default value is: NO. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, diff --git a/tools/doxygen/source-doc.cfg b/tools/doxygen/source-doc.cfg index 89a280be7..dad835fd4 100644 --- a/tools/doxygen/source-doc.cfg +++ b/tools/doxygen/source-doc.cfg @@ -50,7 +50,8 @@ FILE_PATTERNS += */source-doc/*.dox \ */dirinfo.dox # make sure we don't accidently pick up documentation of 3rd party libraries -EXCLUDE_PATTERNS = */libraries/dirinfo.dox +EXCLUDE_PATTERNS = */libraries/dirinfo.dox \ + */windows/vs2015/* EXAMPLE_PATH = source-doc/snippets diff --git a/unix/README.md b/unix/README.md index be5f24f92..79e1b9138 100644 --- a/unix/README.md +++ b/unix/README.md @@ -17,7 +17,6 @@ following packages pre-installed: libboost-dev libboost-date-time-dev - libboost-thread-dev libz-dev libpng-dev libjpeg-dev diff --git a/unix/configure.ac b/unix/configure.ac index bf4d62fe8..c41671671 100644 --- a/unix/configure.ac +++ b/unix/configure.ac @@ -61,7 +61,6 @@ m4_include([unix/config/ax_pthread.m4]) m4_include([unix/config/ax_arg_enable.m4]) m4_include([unix/config/ax_arg_with.m4]) m4_include([unix/config/ax_boost_base.m4]) -m4_include([unix/config/ax_boost_thread.m4]) m4_include([unix/config/ax_test_compiler_flags.m4]) m4_include([unix/config/ax_check_compile_flag.m4]) m4_include([unix/config/ax_check_lib.m4]) @@ -300,44 +299,6 @@ LIBS="$LIBS $PTHREAD_CFLAGS $PTHREAD_LIBS" # append # Boost; required library # the following macro stops with error when boost is not found AX_BOOST_BASE([$required_libboost_version]) -AX_BOOST_THREAD -if test x"$ax_cv_boost_thread" != x"yes"; then - AC_MSG_ERROR([cannot find a suitable boost thread library]) -else - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" # append - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" # append - LIBS="$BOOST_THREAD_LIB $LIBS" -fi -AC_MSG_CHECKING([whether the boost thread library is usable]) -SAVED_LIBS=$LIBS -boost_thread_links=0 -for extralib in '' '-lboost_system' -do - LIBS=$SAVED_LIBS - LIBS="$LIBS $extralib" - AC_RUN_IFELSE([ - AC_LANG_PROGRAM([[ - #include - ]],[[ - boost::mutex m; - boost::defer_lock_t(); - return 0; - ]]) - ],[ - AC_MSG_RESULT([yes]) - BOOST_THREAD_LIB="$BOOST_THREAD_LIB $extralib" - boost_thread_links=1 - ],,[ - AC_MSG_RESULT([cross-compiling]) # FIXME - ]) - if test $boost_thread_links = '1'; then - break - fi -done -if test $boost_thread_links != '1'; then - AC_MSG_RESULT([no]) - AC_MSG_FAILURE([cannot link with the boost thread library]) -fi AC_DEFINE([USE_OFFICIAL_BOOST], [], [Use the official Boost libraries.]) diff --git a/unix/disp_sdl.cpp b/unix/disp_sdl.cpp index 936ec5854..36ddf9e6e 100644 --- a/unix/disp_sdl.cpp +++ b/unix/disp_sdl.cpp @@ -43,6 +43,8 @@ #include +#include + // this must be the last file included #include "syspovdebug.h" diff --git a/unix/install.txt b/unix/install.txt index 4450db2eb..bc7f3ee62 100644 --- a/unix/install.txt +++ b/unix/install.txt @@ -352,12 +352,6 @@ Additional POV-Ray specific options are: requests to find the Boost library in the DIR directory. Boost 1.38 or above is mandatory to build POV-Ray. ---with-boost-thread=special-lib - requests to find the Boost thread library under the special-lib name, for - instance --with-boost-thread=boost_thread-gcc-mt if the thread library is - libboost_thread-gcc-mt.a (static form) or libboost_thread-gcc-mt.so* - (shared form) under the DIR directory specified by the option above. - --with-zlib=DIR or --without-zlib requests to find the ZLIB library in the DIR directory, where DIR is for instance /path/lib if ZLIB is /path/lib/libz.a (static form) or diff --git a/unix/povconfig/syspovconfig_gnu.h b/unix/povconfig/syspovconfig_gnu.h index d118c1cfd..b7320482d 100644 --- a/unix/povconfig/syspovconfig_gnu.h +++ b/unix/povconfig/syspovconfig_gnu.h @@ -61,6 +61,5 @@ #define POV_ULONG unsigned POV_LONG #define MACHINE_INTRINSICS_H -#define ALIGN32 __attribute__ ((aligned(32))) #endif // POVRAY_UNIX_SYSPOVCONFIG_GNU_H diff --git a/unix/povconfig/syspovconfigbackend.h b/unix/povconfig/syspovconfigbackend.h index a9c5f4497..7424d9e6d 100644 --- a/unix/povconfig/syspovconfigbackend.h +++ b/unix/povconfig/syspovconfigbackend.h @@ -11,7 +11,7 @@ /// @parblock /// /// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. -/// Copyright 1991-2018 Persistence of Vision Raytracer Pty. Ltd. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. /// /// POV-Ray is free software: you can redistribute it and/or modify /// it under the terms of the GNU Affero General Public License as @@ -50,10 +50,4 @@ #define POV_USE_DEFAULT_TASK_INITIALIZE 1 #define POV_USE_DEFAULT_TASK_CLEANUP 1 -// Linux machines appear to need more stack storage than the default. -// Note that we leave this setting configurable via `-DPOV_THREAD_STACK_SIZE=...`. -#ifndef POV_THREAD_STACK_SIZE - #define POV_THREAD_STACK_SIZE (4 * 1024 * 1024) // 4 MiB -#endif - #endif // POVRAY_UNIX_SYSPOVCONFIGBACKEND_H diff --git a/unix/povconfig/syspovconfigbase.h b/unix/povconfig/syspovconfigbase.h index 30ad78f2b..7d1dc1b8f 100644 --- a/unix/povconfig/syspovconfigbase.h +++ b/unix/povconfig/syspovconfigbase.h @@ -46,10 +46,20 @@ // Our Unix-specific implementation of the Delay() function currently relies on the presence of // the nanosleep() or usleep() functions. If we have neither of those, we're falling back to // POV-Ray's platform-independent default implementation. -#if defined(HAVE_NANOSLEEP) || defined(HAVE_USLEEP) - #define POV_USE_DEFAULT_DELAY 0 -#else - #define POV_USE_DEFAULT_DELAY 1 +#ifndef POV_USE_PLATFORM_DELAY // allow for flavour-specific override in `syspovconfig.h`. + #if defined(HAVE_NANOSLEEP) + // While the default implementation _should_ do exactly what we want, + // for now we prefer `nanosleep()` because we presume to have a better + // understanding of its limitations and pitfalls. + #define POV_USE_PLATFORM_DELAY 1 + #elif defined(HAVE_USLEEP) + // `usleep()` definitely has some unwieldy quirks, so we presume we'll + // be better off with the default. + #define POV_USE_PLATFORM_DELAY 0 // use 2 for `usleep()` + #else + // We have no other choice but the default. + #define POV_USE_PLATFORM_DELAY 0 + #endif #endif // Our Unix-specific implementation of the Timer class currently relies on the presence of the diff --git a/vfe/unix/unixconsole.cpp b/vfe/unix/unixconsole.cpp index 8acb6c37f..5b492d7e3 100644 --- a/vfe/unix/unixconsole.cpp +++ b/vfe/unix/unixconsole.cpp @@ -39,7 +39,12 @@ // C++ standard header files #include +#include #include +#include + +// Boost library files +#include // Other library header files #include @@ -87,19 +92,34 @@ static bool gCancelRender = false; // for handling asynchronous (external) signals static int gSignalNumber = 0; -static boost::mutex gSignalMutex; +static std::mutex gSignalMutex; +static bool gTerminateSignalHandler = false; + +// TODO FIXME - This way to handle signals seems rather wonky, as it is subject +// to a potential race condition on `gSignalNumber` between `ProcessSignal()` +// polling the signal and `SignalHandler()` processing the next signal. +// Wouldn't it be smarter to register proper signal handlers? static void SignalHandler (void) { - sigset_t sigset; - int signum; + sigset_t sigset; + timespec timeout; + int signum; - while(true) + sigfillset(&sigset); + timeout.tv_sec = 0; + timeout.tv_nsec = 10000000; // 10 ms + + while(!gTerminateSignalHandler) { - sigfillset(&sigset); - sigwait(&sigset, &signum); // wait till a signal is caught - boost::mutex::scoped_lock lock(gSignalMutex); + // Wait till a signal is caught. + signum = sigtimedwait(&sigset, nullptr, &timeout); + if (signum == -1) + continue; // Error. Presumably timed out; check whether to end the task. + + // Got a signal. + std::lock_guard lock(gSignalMutex); gSignalNumber = signum; } } @@ -107,7 +127,7 @@ static void SignalHandler (void) static void ProcessSignal (void) { - boost::mutex::scoped_lock lock(gSignalMutex); + std::lock_guard lock(gSignalMutex); switch (gSignalNumber) { @@ -413,7 +433,7 @@ int main (int argc, char **argv) std::string bench_ini_name; std::string bench_pov_name; sigset_t sigset; - boost::thread *sigthread; + std::thread* sigthread; char ** argv_copy=argv; /* because argv is updated later */ int argc_copy=argc; /* because it might also be updated */ @@ -441,7 +461,7 @@ int main (int argc, char **argv) pthread_sigmask(SIG_BLOCK, &sigset, nullptr); // create the signal handling thread - sigthread = new boost::thread(SignalHandler); + sigthread = new std::thread(SignalHandler); session = new vfeUnixSession(); if (session->Initialize(nullptr, nullptr) != vfeNoError) @@ -479,6 +499,8 @@ int main (int argc, char **argv) PrintStatus (session) ; // TODO: general usage display (not yet in core code) session->GetUnixOptions()->PrintOptions(); + gTerminateSignalHandler = true; + sigthread->join(); delete sigthread; delete session; return RETURN_OK; @@ -487,6 +509,8 @@ int main (int argc, char **argv) { session->Shutdown() ; PrintVersion(); + gTerminateSignalHandler = true; + sigthread->join(); delete sigthread; delete session; return RETURN_OK; @@ -495,6 +519,8 @@ int main (int argc, char **argv) { session->Shutdown(); PrintGeneration(); + gTerminateSignalHandler = true; + sigthread->join(); delete sigthread; delete session; return RETURN_OK; @@ -507,6 +533,8 @@ int main (int argc, char **argv) else { session->Shutdown(); + gTerminateSignalHandler = true; + sigthread->join(); delete sigthread; delete session; return retval; @@ -607,6 +635,8 @@ int main (int argc, char **argv) retval = gCancelRender ? RETURN_USER_ABORT : RETURN_ERROR; session->Shutdown(); PrintStatus (session); + gTerminateSignalHandler = true; + sigthread->join(); delete sigthread; delete session; diff --git a/vfe/unix/vfeplatform.cpp b/vfe/unix/vfeplatform.cpp index daf1382d9..903667afe 100644 --- a/vfe/unix/vfeplatform.cpp +++ b/vfe/unix/vfeplatform.cpp @@ -50,6 +50,9 @@ #include #include +// Boost header files +#include + // other library header files #include #ifdef HAVE_SYS_TIME_H diff --git a/vfe/unix/vfeplatform.h b/vfe/unix/vfeplatform.h index 0be3da362..c8810d076 100644 --- a/vfe/unix/vfeplatform.h +++ b/vfe/unix/vfeplatform.h @@ -40,8 +40,6 @@ #include -#include - #include "base/path_fwd.h" #include "base/stringtypes.h" #include "base/filesystem_fwd.h" diff --git a/vfe/vfe.cpp b/vfe/vfe.cpp index ab97f6336..d6901710c 100644 --- a/vfe/vfe.cpp +++ b/vfe/vfe.cpp @@ -45,6 +45,9 @@ #include #include +#include +#include + #include "base/filesystem.h" #include "base/povassert.h" #include "base/textstream.h" diff --git a/vfe/vfe.h b/vfe/vfe.h index 92602a650..d11eda13d 100644 --- a/vfe/vfe.h +++ b/vfe/vfe.h @@ -41,10 +41,6 @@ #include #include -#include -#include -#include - #include "base/platformbase.h" #include "base/stringtypes.h" #include "base/timer.h" diff --git a/vfe/vfepovms.cpp b/vfe/vfepovms.cpp index 00061106a..274c76862 100644 --- a/vfe/vfepovms.cpp +++ b/vfe/vfepovms.cpp @@ -37,6 +37,9 @@ #include "vfe.h" +#include +#include + #include "povms/povmscpp.h" // this must be the last file included @@ -69,8 +72,8 @@ class SysQNode unsigned int m_ID ; DataNode *m_First ; DataNode *m_Last ; - boost::mutex m_EventMutex ; - boost::condition m_Event ; + std::mutex m_EventMutex ; + std::condition_variable m_Event ; static unsigned int QueueID ; } ; @@ -109,7 +112,7 @@ SysQNode::~SysQNode () { assert (m_Sanity == 0xEDFEEFBE) ; m_Event.notify_all (); - boost::mutex::scoped_lock lock (m_EventMutex); + std::lock_guard lock (m_EventMutex); if (m_Count > 0) { DataNode *current = m_First ; @@ -137,7 +140,7 @@ int SysQNode::Send (void *pData, int Len) dNode->Len = Len ; dNode->Next = nullptr; - boost::mutex::scoped_lock lock (m_EventMutex) ; + std::lock_guard lock (m_EventMutex) ; if (m_Last != nullptr) m_Last->Next = dNode ; @@ -155,7 +158,7 @@ int SysQNode::Send (void *pData, int Len) void *SysQNode::Receive (int *pLen, bool Blocking) { - boost::mutex::scoped_lock lock (m_EventMutex); + std::unique_lock lock (m_EventMutex); assert (m_Sanity == 0xEDFEEFBE) ; if (m_Sanity != 0xEDFEEFBE) @@ -167,11 +170,7 @@ void *SysQNode::Receive (int *pLen, bool Blocking) return nullptr; // TODO: have a shorter wait but loop, and check for system shutdown - // TODO FIXME - boost::xtime has been deprecated since boost 1.34. - boost::xtime t; - boost::xtime_get (&t, POV_TIME_UTC); - t.nsec += 50000000 ; - m_Event.timed_wait (lock, t); + m_Event.wait_for (lock, std::chrono::milliseconds(50)); if (m_Count == 0) return nullptr; diff --git a/vfe/vfeprecomp.h b/vfe/vfeprecomp.h index 6aa72d4eb..d1f61db2e 100644 --- a/vfe/vfeprecomp.h +++ b/vfe/vfeprecomp.h @@ -1,79 +1,74 @@ -//****************************************************************************** -/// -/// @file vfe/vfeprecomp.h -/// -/// Precompiled header for the user interface portions of POV-Ray. -/// -/// @copyright -/// @parblock -/// -/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. -/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. -/// -/// POV-Ray is free software: you can redistribute it and/or modify -/// it under the terms of the GNU Affero General Public License as -/// published by the Free Software Foundation, either version 3 of the -/// License, or (at your option) any later version. -/// -/// POV-Ray is distributed in the hope that it will be useful, -/// but WITHOUT ANY WARRANTY; without even the implied warranty of -/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -/// GNU Affero General Public License for more details. -/// -/// You should have received a copy of the GNU Affero General Public License -/// along with this program. If not, see . -/// -/// ---------------------------------------------------------------------------- -/// -/// POV-Ray is based on the popular DKB raytracer version 2.12. -/// DKBTrace was originally written by David K. Buck. -/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. -/// -/// @endparblock -/// -//****************************************************************************** - -/// @file -/// @note -/// @parblock -/// This header file is _not_ explicitly included in any source file (except @ref vfe/vfeprecomp.cpp -/// which is designed to allow for precompiling this header in the first place). To use -/// precompiled headers, you will therefore have to make your build environment automatically -/// inject this header at the start of every source file. -/// -/// The rationale behind this is to keep the set of headers included in each source file at an -/// absolute minimum when precompiled headers are _not_ used. -/// @endparblock - -#include "base/configbase.h" // only pulled in for POV_MULTITHREADED - -// C++ variants of C standard header files -#include -#include -#include -#include -#include -#include -#include -#include - -// C++ standard header files -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Boost header files -#include -#include -#include -#if POV_MULTITHREADED -#include -#endif \ No newline at end of file +//****************************************************************************** +/// +/// @file vfe/vfeprecomp.h +/// +/// Precompiled header for the user interface portions of POV-Ray. +/// +/// @copyright +/// @parblock +/// +/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. +/// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. +/// +/// POV-Ray is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License as +/// published by the Free Software Foundation, either version 3 of the +/// License, or (at your option) any later version. +/// +/// POV-Ray is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program. If not, see . +/// +/// ---------------------------------------------------------------------------- +/// +/// POV-Ray is based on the popular DKB raytracer version 2.12. +/// DKBTrace was originally written by David K. Buck. +/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. +/// +/// @endparblock +/// +//****************************************************************************** + +/// @file +/// @note +/// @parblock +/// This header file is _not_ explicitly included in any source file (except @ref vfe/vfeprecomp.cpp +/// which is designed to allow for precompiling this header in the first place). To use +/// precompiled headers, you will therefore have to make your build environment automatically +/// inject this header at the start of every source file. +/// +/// The rationale behind this is to keep the set of headers included in each source file at an +/// absolute minimum when precompiled headers are _not_ used. +/// @endparblock + +#include "base/configbase.h" // only pulled in for POV_MULTITHREADED + +// C++ variants of C standard header files +#include +#include +#include +#include +#include +#include +#include +#include + +// C++ standard header files +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Boost header files +#include diff --git a/vfe/vfesession.cpp b/vfe/vfesession.cpp index e857812dd..8d8ccb72f 100644 --- a/vfe/vfesession.cpp +++ b/vfe/vfesession.cpp @@ -41,6 +41,11 @@ #endif #include "vfe.h" + +#include + +#include + #include "backend/povray.h" static POVMSContext POVMS_Output_Context = nullptr; @@ -165,7 +170,7 @@ void vfeSession::SetSucceeded (bool ok) // Clears all messages from the status message queue. void vfeSession::ClearStatusMessages() { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); while (m_StatusQueue.empty() == false) m_StatusQueue.pop(); @@ -199,7 +204,7 @@ void vfeSession::AppendStreamMessage (MessageType type, const char *message, boo const char *begin = message ; const char *end = begin + strlen (message) - 1; - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); for (const char *s = begin ; s <= end ; s++) { @@ -226,7 +231,7 @@ void vfeSession::AppendStreamMessage (MessageType type, const boost::format& fmt void vfeSession::AppendErrorMessage (const string& Msg) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); bool possibleError = Msg.find("Possible ") == 0 ; // for the purpose of setting m_HadErrorMessage, we don't consider a @@ -242,7 +247,7 @@ void vfeSession::AppendErrorMessage (const string& Msg) void vfeSession::AppendErrorMessage (const string& Msg, const UCS2String& File, int Line, int Col) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); bool possibleError = Msg.find("Possible ") == 0 ; // for the purpose of setting m_HadErrorMessage, we don't consider a @@ -258,7 +263,7 @@ void vfeSession::AppendErrorMessage (const string& Msg, const UCS2String& File, void vfeSession::AppendWarningMessage (const string& Msg) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); m_MessageQueue.push (GenericMessage (*this, mWarning, Msg)); if (m_MaxGenericMessages != -1) @@ -269,7 +274,7 @@ void vfeSession::AppendWarningMessage (const string& Msg) void vfeSession::AppendWarningMessage (const string& Msg, const UCS2String& File, int Line, int Col) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); m_MessageQueue.push (GenericMessage (*this, mWarning, Msg, File, Line, Col)); if (m_MaxGenericMessages != -1) @@ -280,7 +285,7 @@ void vfeSession::AppendWarningMessage (const string& Msg, const UCS2String& File void vfeSession::AppendStatusMessage (const string& Msg, int RecommendedPause) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); m_StatusQueue.push (StatusMessage (*this, Msg, RecommendedPause)); m_StatusLineMessage = Msg; @@ -292,7 +297,7 @@ void vfeSession::AppendStatusMessage (const string& Msg, int RecommendedPause) void vfeSession::AppendStatusMessage (const boost::format& fmt, int RecommendedPause) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); m_StatusQueue.push (StatusMessage (*this, fmt.str(), RecommendedPause)); m_StatusLineMessage = fmt.str(); @@ -304,7 +309,7 @@ void vfeSession::AppendStatusMessage (const boost::format& fmt, int RecommendedP void vfeSession::AppendAnimationStatus (int FrameId, int SubsetFrame, int SubsetTotal, const UCS2String& Filename) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); m_CurrentFrameId = FrameId; m_CurrentFrame = SubsetFrame; @@ -339,7 +344,7 @@ bool vfeSession::GetNextCombinedMessage (MessageType &Type, string& Message) POV_LONG mqTime = 0x7fffffffffffffffLL ; POV_LONG sqTime = 0x7fffffffffffffffLL ; POV_LONG cqTime = 0x7fffffffffffffffLL ; - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); if (m_MessageQueue.empty() && m_StatusQueue.empty() && m_ConsoleQueue.empty()) return (false); @@ -385,7 +390,7 @@ bool vfeSession::GetNextNonStatusMessage (MessageType &Type, string& Message, UC { POV_LONG mqTime = 0x7fffffffffffffffLL ; POV_LONG cqTime = 0x7fffffffffffffffLL ; - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); if (m_MessageQueue.empty() && m_ConsoleQueue.empty()) return (false); @@ -455,7 +460,7 @@ bool vfeSession::GetNextNonStatusMessage (MessageType &Type, string& Message) // as a parameter, then returns true. bool vfeSession::GetNextStatusMessage (StatusMessage& Message) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); if (m_StatusQueue.empty()) return (false); @@ -470,7 +475,7 @@ bool vfeSession::GetNextStatusMessage (StatusMessage& Message) // parameter, then returns true. bool vfeSession::GetNextGenericMessage (GenericMessage& Message) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); if (m_MessageQueue.empty()) return (false); @@ -485,7 +490,7 @@ bool vfeSession::GetNextGenericMessage (GenericMessage& Message) // then returns true. bool vfeSession::GetNextConsoleMessage (MessageBase& Message) { - boost::mutex::scoped_lock lock(m_MessageMutex); + std::lock_guard lock(m_MessageMutex); if (m_ConsoleQueue.empty()) return (false); @@ -653,7 +658,7 @@ void vfeSession::WorkerThread() } m_RequestEvent.notify_all (); } - boost::thread::yield(); + std::this_thread::yield(); } catch (pov_base::Exception& e) { @@ -903,7 +908,7 @@ const char *vfeSession::GetErrorString(int code) const // provided for VFE does this). vfeStatusFlags vfeSession::GetStatus(bool Clear, int WaitTime) { - boost::mutex::scoped_lock lock (m_SessionMutex); + std::unique_lock lock (m_SessionMutex); if ((m_StatusFlags & m_EventMask) != 0) { @@ -916,12 +921,7 @@ vfeStatusFlags vfeSession::GetStatus(bool Clear, int WaitTime) if (WaitTime > 0) { - // TODO FIXME - boost::xtime has been deprecated since boost 1.34. - boost::xtime t; - boost::xtime_get (&t, POV_TIME_UTC); - t.sec += WaitTime / 1000 ; - t.nsec += (WaitTime % 1000) * 1000000 ; - m_SessionEvent.timed_wait (lock, t); + m_SessionEvent.wait_for (lock, std::chrono::milliseconds(WaitTime)); } else if (WaitTime == -1) m_SessionEvent.wait (lock); @@ -978,18 +978,14 @@ bool vfeSession::Paused() const // vfeSession::Initialize() hasn't been called or failed when called). bool vfeSession::Pause() { - boost::mutex::scoped_lock lock (m_RequestMutex); + std::unique_lock lock (m_RequestMutex); CheckFrontend(); // we can't call pause directly since it will result in a thread context // error. pause must be called from the context of the worker thread. - // TODO FIXME - boost::xtime has been deprecated since boost 1.34. - boost::xtime t; - boost::xtime_get (&t, POV_TIME_UTC); - t.sec += 3 ; m_RequestFlag = rqPauseRequest; - if (m_RequestEvent.timed_wait(lock, t) == false) + if (m_RequestEvent.wait_for(lock, std::chrono::seconds(3)) == std::cv_status::timeout) { m_RequestFlag = rqNoRequest; m_LastError = vfeRequestTimedOut; @@ -1002,18 +998,14 @@ bool vfeSession::Pause() // The converse of vfeSession::Pause(). All the same considerations apply. bool vfeSession::Resume() { - boost::mutex::scoped_lock lock (m_RequestMutex); + std::unique_lock lock (m_RequestMutex); CheckFrontend(); // we can't call resume directly since it will result in a thread context // error. it must be called from the context of the worker thread. - // TODO FIXME - boost::xtime has been deprecated since boost 1.34. - boost::xtime t; - boost::xtime_get (&t, POV_TIME_UTC); - t.sec += 3 ; m_RequestFlag = rqResumeRequest; - if (m_RequestEvent.timed_wait(lock, t) == false) + if (m_RequestEvent.wait_for(lock, std::chrono::seconds(3)) == std::cv_status::timeout) { m_RequestFlag = rqNoRequest; m_LastError = vfeRequestTimedOut; @@ -1026,7 +1018,7 @@ bool vfeSession::Resume() // Internal method used to generate an event notification. void vfeSession::NotifyEvent(vfeStatusFlags Status) { - boost::mutex::scoped_lock lock (m_SessionMutex); + std::lock_guard lock (m_SessionMutex); m_StatusFlags = vfeStatusFlags(m_StatusFlags | Status); if ((m_StatusFlags & m_EventMask) != 0) @@ -1055,7 +1047,7 @@ void vfeSession::NotifyEvent(vfeStatusFlags Status) // connection with the backend code. int vfeSession::Initialize(vfeDestInfo *Dest, vfeAuthInfo *Auth) { - boost::mutex::scoped_lock lock (m_InitializeMutex); + std::unique_lock lock (m_InitializeMutex); // params must be `nullptr` in this version if ((Dest != nullptr) || (Auth != nullptr)) @@ -1075,18 +1067,14 @@ int vfeSession::Initialize(vfeDestInfo *Dest, vfeAuthInfo *Auth) m_MessageCount = 0; m_LastError = vfeNoError; - // TODO FIXME - boost::xtime has been deprecated since boost 1.34. - boost::xtime t; - boost::xtime_get (&t, POV_TIME_UTC); - t.sec += 3 ; + auto timeout = 3; #ifdef _DEBUG - t.sec += 120; + timeout += 120; #endif - t.nsec = 0; - m_WorkerThread = new boost::thread(vfeSessionWorker(*this)); + m_WorkerThread = new std::thread(vfeSessionWorker(*this)); // TODO FIXME: see thread <47ca756c$1@news.povray.org> - if (m_BackendState == kUnknown && m_InitializeEvent.timed_wait(lock, t) == false) + if ((m_BackendState == kUnknown) && (m_InitializeEvent.wait_for(lock, std::chrono::seconds(timeout)) == std::cv_status::timeout)) { m_WorkerThreadShutdownRequest = true ; m_Initialized = false ; diff --git a/vfe/vfesession.h b/vfe/vfesession.h index 67edc574d..f46cfb672 100644 --- a/vfe/vfesession.h +++ b/vfe/vfesession.h @@ -39,13 +39,17 @@ #ifndef POVRAY_VFE_VFESESSION_H #define POVRAY_VFE_VFESESSION_H +#include #include +#include #include +// not required for `std::thread` because we forward-declare it in `base/base_fwd.h` #include -#include -#include +#include +#include +#include "base/base_fwd.h" #include "base/stringutilities.h" #include "frontend/simplefrontend.h" @@ -1280,20 +1284,20 @@ namespace vfe VirtualFrontEnd *m_Frontend; State m_BackendState; - boost::mutex m_MessageMutex; - boost::mutex m_SessionMutex; - boost::condition m_SessionEvent; - boost::mutex m_InitializeMutex; - boost::condition m_InitializeEvent; - boost::condition m_ShutdownEvent; - boost::thread *m_WorkerThread; - boost::thread *m_BackendThread; + std::mutex m_MessageMutex; + std::mutex m_SessionMutex; + std::condition_variable m_SessionEvent; + std::mutex m_InitializeMutex; + std::condition_variable m_InitializeEvent; + std::condition_variable m_ShutdownEvent; + std::thread *m_WorkerThread; + std::thread *m_BackendThread; volatile bool m_WorkerThreadExited; volatile bool m_BackendThreadExited; volatile bool m_WorkerThreadShutdownRequest; - boost::mutex m_RequestMutex; - boost::condition m_RequestEvent; + std::mutex m_RequestMutex; + std::condition_variable m_RequestEvent; volatile int m_RequestFlag; volatile int m_RequestResult; } ; diff --git a/windows/povconfig/syspovconfig.h b/windows/povconfig/syspovconfig.h index fc8ac415a..eb2ceed09 100644 --- a/windows/povconfig/syspovconfig.h +++ b/windows/povconfig/syspovconfig.h @@ -108,16 +108,6 @@ ///////////////////////////////////////////////////////////// -#ifndef __GENDEFS - #define __GENDEFS - typedef unsigned char uchar; - typedef unsigned short ushort; - typedef unsigned int uint; - typedef unsigned long ulong; - typedef unsigned __int64 uint64; - typedef __int64 int64; -#endif - #ifdef __INTEL_COMPILER // Intel C++ whines about the lack of a return on RDTSC() for each and every file // it is included in. VC++ is smarter (or dumber, depending on your point of view). @@ -140,7 +130,8 @@ namespace povwin void win_free(void *p, const void *ptr, int line); char *win_strdup(const char *s); char *win_strdup(const char *s, const void *ptr, int line); - bool WinMemReport(bool global, uint64& allocs, uint64& frees, int64& current, uint64& peak, uint64& smallest, uint64& largest); + bool WinMemReport(bool global, unsigned __int64& allocs, unsigned __int64& frees, __int64& current, + unsigned __int64& peak, unsigned __int64& smallest, unsigned __int64& largest); void WinMemStage(bool BeginRender, void *cookie = NULL); #endif @@ -160,7 +151,6 @@ namespace povwin #endif #define ALTMAIN -#define LITTLE_ENDIAN #define POV_PATH_SEPARATOR '\\' #define POV_IS_PATH_SEPARATOR(c) (((c) == POV_PATH_SEPARATOR) || ((c) == '/')) #define POV_SLASH_IS_SWITCH_CHARACTER 1 // allow forward slash as a switch character (even despite its use as a path separator!) @@ -173,10 +163,6 @@ namespace povwin #define POV_SYS_IMAGE_EXTENSION ".bmp" #define POV_SYS_IMAGE_TYPE BMP #define POV_FILENAME_BUFFER_CHARS (_MAX_PATH-1) // (NB: _MAX_PATH includes terminating NUL character) -#define USE_OFFICIAL_BOOST 1 - -#define POV_MEMMOVE(dst,src,len) std::memmove((dst),(src),(len)) -#define POV_MEMCPY(dst,src,len) std::memcpy((dst),(src),(len)) #ifdef _CONSOLE diff --git a/windows/povconfig/syspovconfig_msvc.h b/windows/povconfig/syspovconfig_msvc.h index e7dc82676..7f3e77998 100644 --- a/windows/povconfig/syspovconfig_msvc.h +++ b/windows/povconfig/syspovconfig_msvc.h @@ -104,7 +104,6 @@ // MS Visual C++ 2005 (aka 8.0), compiling for 64 bit target #define POV_COMPILER_VER "msvc8" #define METADATA_COMPILER_STRING "msvc 8" - #define ALIGN16 __declspec(align(16)) inline const int& max(const int& _X, const int& _Y) {return (_X < _Y ? _Y : _X); } inline const int& min(const int& _X, const int& _Y) {return (_Y < _X ? _Y : _X); } inline const unsigned int& max(const unsigned int& _X, const unsigned int& _Y) {return (_X < _Y ? _Y : _X); } @@ -226,7 +225,6 @@ #undef ReturnAddress #define ReturnAddress() _ReturnAddress() -#define ALIGN32 __declspec(align(32)) #define MACHINE_INTRINSICS_H #if _MSC_VER >= 1600 diff --git a/windows/povconfig/syspovconfigbase.h b/windows/povconfig/syspovconfigbase.h index b2f90dabe..e6646b8ec 100644 --- a/windows/povconfig/syspovconfigbase.h +++ b/windows/povconfig/syspovconfigbase.h @@ -49,7 +49,8 @@ #endif // Windows provides a platform-specific mechanism to let a task wait for a specified time. -#define POV_USE_DEFAULT_DELAY 0 +// However, the C++11 standard mechanism should be fine. +#define POV_USE_PLATFORM_DELAY 0 // Windows provides platform-specific mechanisms to measure both wall-clock and CPU time. #define POV_USE_DEFAULT_TIMER 0 diff --git a/windows/pvdisplay.cpp b/windows/pvdisplay.cpp index 3c58f7598..10a0ff024 100644 --- a/windows/pvdisplay.cpp +++ b/windows/pvdisplay.cpp @@ -369,10 +369,11 @@ inline void WinLegacyDisplay::SetPixel (unsigned int x, unsigned int y, const po unsigned char *p = m_BitmapSurface + (m_Bitmap.header.biHeight - 1 - y) * m_BytesPerLine + x * 3 ; if (pov_frontend::UseAlpha && colour->alpha < 255) { - uint backColor = (x & 8) == (y & 8) ? (uint) (255 - colour->alpha) * 0xff : (uint) (255 - colour->alpha) * 0xc0 ; - *p++ = (unsigned char) (((uint) colour->blue * colour->alpha + backColor) / 255) ; - *p++ = (unsigned char) (((uint) colour->green * colour->alpha + backColor) / 255) ; - *p++ = (unsigned char) (((uint) colour->red * colour->alpha + backColor) / 255) ; + unsigned int backColor = (x & 8) == (y & 8) ? (unsigned int) (255 - colour->alpha) * 0xff : + (unsigned int) (255 - colour->alpha) * 0xc0 ; + *p++ = (unsigned char) (((unsigned int) colour->blue * colour->alpha + backColor) / 255) ; + *p++ = (unsigned char) (((unsigned int) colour->green * colour->alpha + backColor) / 255) ; + *p++ = (unsigned char) (((unsigned int) colour->red * colour->alpha + backColor) / 255) ; } else { diff --git a/windows/pvengine.cpp b/windows/pvengine.cpp index ad589877a..2aa31190c 100644 --- a/windows/pvengine.cpp +++ b/windows/pvengine.cpp @@ -80,6 +80,7 @@ #include #include +#include #include "pvengine.h" #include "resource.h" @@ -567,7 +568,7 @@ void WIN32_DEBUG_FILE_OUTPUT (const char *format,...) { va_list arg_ptr ; static FILE *f ; - static boost::mutex mtx; + static std::mutex mtx; if (format == NULL) { @@ -586,7 +587,7 @@ void WIN32_DEBUG_FILE_OUTPUT (const char *format,...) return ; } - boost::mutex::scoped_lock l(mtx); + std::lock_guard l(mtx); fprintf (f, "%u [%d]: ", GetTickCount (), GetCurrentThreadId ()) ; va_start (arg_ptr, format) ; vfprintf (f, format, arg_ptr) ; @@ -1713,8 +1714,8 @@ LONG WINAPI ExceptionHandler(struct _EXCEPTION_POINTERS* ExceptionInfo) long timestamp = _time32(NULL); PCONTEXT c ; static char str[2048] ; - static boost::mutex mtx; - boost::mutex::scoped_lock l(mtx); + static std::mutex mtx; + std::lock_guard l(mtx); c = ExceptionInfo->ContextRecord ; const char *desc = GetExceptionDescription(ExceptionInfo->ExceptionRecord->ExceptionCode); @@ -5067,11 +5068,11 @@ void LZTimerOff (void) PerformanceCounter2 = 0 ; } -ulong LZTimerCount (void) +unsigned long LZTimerCount (void) { if (PerformanceCounter1 == 0 || PerformanceCounter2 < PerformanceCounter1) return (0) ; - return ((ulong) ((PerformanceCounter2 - PerformanceCounter1) / PerformanceScale)) ; + return ((unsigned long) ((PerformanceCounter2 - PerformanceCounter1) / PerformanceScale)) ; } __int64 LZTimerRawCount (void) diff --git a/windows/pvengine.h b/windows/pvengine.h index b68c21985..1d2db7272 100644 --- a/windows/pvengine.h +++ b/windows/pvengine.h @@ -72,23 +72,16 @@ #define MAX_MESSAGE 1024 #define MAX_ARGV 256 -#define TOOLFILENAME "PVTOOLS.INI" #define MAX_TOOLCMD 32 #define MAX_TOOLCMDTEXT 128 #define MAX_TOOLHELPTEXT 128 -#define MIN_EDITOR_VERSION 100 -#define MAX_EDITOR_VERSION 199 #define MAX_WINDOWS 16 #define MAX_EDIT_FILES 32 #define POV_INTERNAL_STREAM ((FILE *) 1L) -#define LEGACY_OPTION_FILE_SUPPORT - #define EDIT_FILE 1 #define RENDER_FILE 2 -#define CRASH_REPORTER_EXECUTABLE "SubmitMinidump.exe" - #if POV_RAY_IS_OFFICIAL #ifdef _WIN64 #define CLASSNAMEPREFIX "Pov" POV_RAY_MAJOR_VERSION POV_RAY_MINOR_VERSION "-Win64-" @@ -114,14 +107,12 @@ #endif #ifdef _WIN64 - #define BINDIRNAME "bin64" #define INSTALLTIMEKEY "InstallTime64" // NB: We're using the standard editor DLLs regardless of architecture optimization (e.g. AVX) #define EDITDLLNAME "cmedit64.dll" #define EDITDLLNAME_DEBUG "cmedit64d.dll" #define VERSIONVAL POVWIN_BETA_PREFIX "VersionNo64" #else - #define BINDIRNAME "bin32" #define INSTALLTIMEKEY "InstallTime32" // TODO - use the standard editor DLLs regardless of architecture optimization (e.g. SSE2) #ifdef BUILD_SSE2 @@ -137,32 +128,11 @@ // message definitions used to be here but have been moved to pvedit.h. // ---------------------------------------------------------------------- -#define NUM_BUTTONS 16 #define HDIB HANDLE #define SEPARATOR '\\' #define DRAWFASTRECT(hdc,lprc) ExtTextOut(hdc,0,0,ETO_OPAQUE,lprc,NULL,0,NULL) -#define RGBBLACK RGB(0,0,0) -#define RGBRED RGB(128,0,0) -#define RGBGREEN RGB(0,128,0) -#define RGBBLUE RGB(0,0,128) - -#define RGBBROWN RGB(128,128,0) -#define RGBMAGENTA RGB(128,0,128) -#define RGBCYAN RGB(0,128,128) -#define RGBLTGRAY RGB(192,192,192) - -#define RGBGRAY RGB(128,128,128) -#define RGBLTRED RGB(255,0,0) -#define RGBLTGREEN RGB(0,255,0) -#define RGBLTBLUE RGB(0,0,255) - -#define RGBYELLOW RGB(255,255,0) -#define RGBLTMAGENTA RGB(255,0,255) -#define RGBLTCYAN RGB(0,255,255) -#define RGBWHITE RGB(255,255,255) - namespace povwin { @@ -227,48 +197,6 @@ typedef struct PALETTEENTRY pe [256] ; } LogPal ; -typedef struct -{ - bool ncEnabled ; - bool menuWasUp ; - bool hasCaption ; - bool hasBorder ; - bool hasSizeableBorder ; - bool hasStatusBar ; - bool hasMenuBar ; - bool sysMenuOverride ; - bool isMaxiMinimized ; - HWND hWnd ; - HFONT hMenuBarFont ; - HFONT hStatusBarFont ; - HFONT hSystemFont ; - ushort captionTotal ; - ushort captionInternal ; - ushort captionBorderLeft ; - ushort captionBorderRight ; - ushort captionBorderTop ; - ushort captionBorderBottom ; - ushort borderWidth ; - ushort borderHeight ; - ushort buttonWidth ; - ushort buttonHeight ; - ushort sizing ; - ushort statusBarTotal ; - ushort statusBarBorder ; - ushort menuBarTotal ; - ushort menuBarBorder ; -} pvncStruct ; - -class AutoLock final -{ -public: - inline AutoLock (CRITICAL_SECTION& CriticalSection) { m_CriticalSection = &CriticalSection ; EnterCriticalSection (m_CriticalSection) ; } - inline ~AutoLock() { LeaveCriticalSection (m_CriticalSection) ; } - -private: - LPCRITICAL_SECTION m_CriticalSection ; -}; - inline int MulDivNoRound (int value, int mul_by, int div_by) { return ((int) ((__int64) value * mul_by / div_by)) ; @@ -297,7 +225,6 @@ void message_printf (const char *format, ...) ; void wrapped_printf (const char *format, ...) ; void dump_pane_to_clipboard (void) ; bool copy_text_to_clipboard(const char *text); -bool PutPrivateProfileInt (LPCSTR lpszSection, LPCSTR lpszEntry, UINT uiValue, LPCSTR lpszFilename) ; void get_logfont (HDC hdc, LOGFONT *lf) ; int create_message_font (HDC hdc, LOGFONT *lf) ; void status_printf (int nSection, const char *format, ...) ; @@ -309,10 +236,8 @@ bool hasTrailingPathSeparator (const char *s) ; void trimTrailingPathSeparator (char *s) ; void validatePath (char *s) ; int joinPath (char *out, const char *path, const char *name) ; -void UpdateTabbedWindow (int current, bool force) ; void CalculateClientWindows (bool redraw) ; bool start_rendering (bool ignore_source_file) ; -bool HaveWin95 (void) ; void render_stopped (void) ; void cancel_render (void) ; void SetStatusPanelItemText (int id, LPCSTR format, ...) ; @@ -332,7 +257,6 @@ void cloneOldIni(const std::string& oldPath, const std::string& newPath); void update_menu_for_render (bool rendering) ; void update_queue_status (bool write_files) ; void draw_ordinary_listbox (DRAWITEMSTRUCT *d, bool fitpath) ; -void fill_statistics_listbox (HWND hlb, int id) ; void resize_listbox_dialog (HWND hDlg, int idLb, int chars) ; void CenterWindowRelative (HWND hRelativeTo, HWND hTarget, bool bRepaint, bool checkBorders) ; void FitWindowInWindow (HWND hRelativeTo, HWND hTarget) ; @@ -343,20 +267,14 @@ void set_toggles (void) ; void load_tool_menu (char *iniFilename) ; char *parse_tool_command (char *command) ; char *get_elapsed_time (int seconds) ; -void initialise_statusbar (bool isMaxiMiniMode) ; -void calculate_statusbar (void) ; -void paint_statusbar (int nSection) ; void extract_ini_sections (char *filename, HWND hwnd) ; void extract_ini_sections_ex (char *filename, HWND hwnd) ; int select_combo_item_ex (HWND hwnd, char *s) ; -void paint_rendering_signal (int which_one) ; char *get_full_name (char *s) ; bool PovInvalidateRect (HWND hWnd, CONST RECT *lpRect, bool bErase) ; -int load_editors (char *iniFilename) ; bool TaskBarAddIcon (HWND hwnd, UINT uID, HICON hicon, LPSTR lpszTip) ; bool TaskBarModifyIcon (HWND hwnd, UINT uID, LPSTR lpszTip) ; bool TaskBarDeleteIcon (HWND hwnd, UINT uID) ; -bool TestAccessAllowed (const char *Filename, unsigned int FileType, bool IsWrite) ; char *clean (char *s) ; bool fileExists (const char *filename) ; bool dirExists (const char *filename) ; @@ -368,8 +286,6 @@ bool PutHKCU(const char *Section, const char *Name, const std::string& Value); bool PutHKCU(const char *Section, const char *Name, unsigned Value); unsigned GetHKCU(const char *Section, const char *Name, unsigned DefaultValue); size_t GetHKCU(const char *Section, const char *Name, const char *DefaultValue, char *Buffer, unsigned MaxLength); -bool read_legacy_INI_settings (const char *iniFilename, const char *oldHome, const char *newHome); -void clone_legacy_dir_restrictions (const char *iniFilename, const char *oldHome, const char *newHome); // file PVFILES.C @@ -390,23 +306,17 @@ void clear_menu (HMENU hMenu) ; void build_main_menu (HMENU hMenu, bool have_editor) ; void build_editor_menu (HMENU hMenu) ; void set_newuser_menus (bool hide) ; -void swap_renderwin_menu (void) ; int find_menuitem (HMENU hMenu, LPCSTR title) ; // file PVTEXT.C void write_wrapped_text (HDC hdc, RECT *rect, const char *text) ; void tip_of_the_day (HDC hdc, RECT *rect, char *text) ; -void paint_statusbar (int nSection) ; void say_status_message (int section, const char *message) ; void handle_menu_select (WPARAM wParam, LPARAM lParam) ; char *clean_str (const char *s) ; HWND create_toolbar (HWND hwndParent) ; -HWND create_tabbed_window (HWND hwndParent) ; -void initialise_tabbed_window (HWND hwnd) ; -unsigned add_window_to_tab (HWND hwnd, void *editor, char *s) ; void resize_windows (unsigned left, unsigned top, unsigned width, unsigned height) ; -unsigned get_tab_index (HWND hwnd, void *editor) ; char *preparse_commandline (char *s) ; char *preparse_instance_commandline (char *s) ; void add_edit_file (char *file); @@ -417,11 +327,6 @@ HWND CreateStatusbar (HWND hwndParent) ; void ResizeStatusBar (HWND hwnd) ; bool HandleStatusTooltip(NMHDR *nmh); -// file PVPOVMS.CPP - -bool WIN_POVMS_Init (void) ; -void WIN_POVMS_Shutdown (void) ; - // file PVBITMAP.CPP HDIB FAR BitmapToDIB (HBITMAP hBitmap, HPALETTE hPal); @@ -438,7 +343,6 @@ HDIB FAR CopyWindowToDIB (HWND, WORD); HPALETTE FAR CreateDIBPalette (HDIB hDIB); HDIB FAR CreateDIB(DWORD, DWORD, WORD); WORD FAR DestroyDIB (HDIB); -void FAR DIBError (int ErrNo); DWORD FAR DIBHeight (LPSTR lpDIB); WORD FAR DIBNumColors (LPSTR lpDIB); HBITMAP FAR DIBToBitmap (HDIB hDIB, HPALETTE hPal); @@ -540,7 +444,7 @@ RGBQUAD halftonePal [256] = // Division lookup tables. These tables compute 0-255 divided by 51 and // modulo 51. These tables could approximate gamma correction. -uchar div51 [256] = +unsigned char div51 [256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -555,7 +459,7 @@ uchar div51 [256] = 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5 } ; -uchar mod51 [256] = +unsigned char mod51 [256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, @@ -575,12 +479,12 @@ uchar mod51 [256] = // Multiplication lookup tables. These compute 0-5 times 6 and 36. -uchar mul6 [6] = {0, 6, 12, 18, 24, 30} ; -uchar mul36 [6] = {0, 36, 72, 108, 144, 180} ; +unsigned char mul6 [6] = {0, 6, 12, 18, 24, 30} ; +unsigned char mul36 [6] = {0, 36, 72, 108, 144, 180} ; // Ordered 8x8 dither matrix for 8 bit to 2.6 bit halftones. -uchar dither8x8 [64] = +unsigned char dither8x8 [64] = { 0, 38, 9, 47, 2, 40, 11, 50, 25, 12, 35, 22, 27, 15, 37, 24, diff --git a/windows/pvmem.cpp b/windows/pvmem.cpp index baed99699..05827ca80 100644 --- a/windows/pvmem.cpp +++ b/windows/pvmem.cpp @@ -153,7 +153,8 @@ void WinMemStage(bool BeginRender, void *cookie) TrackMem = false; } -bool WinMemReport(bool global, uint64& allocs, uint64& frees, int64& current, uint64& peak, uint64 &smallest, uint64 &largest) +bool WinMemReport(bool global, unsigned __int64& allocs, unsigned __int64& frees, __int64& current, + unsigned __int64& peak, unsigned __int64& smallest, unsigned __int64& largest) { if (!global) return false; @@ -200,7 +201,8 @@ void WinMemThreadCleanup() delete lMemStats; } -bool WinMemReport(bool global, uint64& allocs, uint64& frees, int64& current, uint64& peak, uint64 &smallest, uint64 &largest) +bool WinMemReport(bool global, unsigned __int64& allocs, unsigned __int64& frees, __int64& current, + unsigned __int64& peak, unsigned __int64 &smallest, unsigned __int64 &largest) { HeapLock lock(gHeap); diff --git a/windows/pvmem.h b/windows/pvmem.h index 90dab19e1..82bc01dec 100644 --- a/windows/pvmem.h +++ b/windows/pvmem.h @@ -82,7 +82,8 @@ class WinMemStats final { } - void Report(uint64& allocs, uint64& frees, int64& current, uint64& peak, uint64 &smallest, uint64 &largest) + void Report(unsigned __int64& allocs, unsigned __int64& frees, __int64& current, + unsigned __int64& peak, unsigned __int64& smallest, unsigned __int64& largest) { allocs = callsToAlloc; frees = callsToFree; @@ -130,12 +131,12 @@ class WinMemStats final } private: - volatile int64 currentAllocated; - volatile uint64 peakAllocated; - volatile uint64 callsToAlloc; - volatile uint64 callsToFree; - volatile uint64 smallestAlloc; - volatile uint64 largestAlloc; + volatile __int64 currentAllocated; + volatile unsigned __int64 peakAllocated; + volatile unsigned __int64 callsToAlloc; + volatile unsigned __int64 callsToFree; + volatile unsigned __int64 smallestAlloc; + volatile unsigned __int64 largestAlloc; }; typedef WinMemStats PovMemStats; diff --git a/windows/pvtext.cpp b/windows/pvtext.cpp index e6d973885..50e68d77c 100644 --- a/windows/pvtext.cpp +++ b/windows/pvtext.cpp @@ -358,7 +358,7 @@ void buffer_message (msgtype message_type, const char *s, bool addLF) message_type = mHorzLine ; strcpy (s1 + 1, str_buffer) ; - *s1 = (uchar) message_type ; + *s1 = (unsigned char) message_type ; if (lf == CR) { @@ -432,7 +432,7 @@ void add_single_line (msgtype message_type, const char *str) } strcpy (s1 + 1, str) ; - *s1 = (uchar) message_type ; + *s1 = (unsigned char) message_type ; if (*next_message) { diff --git a/windows/vs2015/console.vcxproj b/windows/vs2015/console.vcxproj index 40687cf30..bfb56ab19 100644 --- a/windows/vs2015/console.vcxproj +++ b/windows/vs2015/console.vcxproj @@ -353,9 +353,6 @@ - - {d870a978-8130-4d1d-9fb2-3ee2028d2c50} - {39c65232-04fb-4622-8283-34829739887c} false @@ -369,12 +366,6 @@ {7df42126-d237-41d3-9abe-a3acc8bac56e} - - {35a2dc31-84bc-4f7a-9c93-1d072432ad79} - - - {10b193d4-e27b-4438-a825-bfb3d2b4c74d} - {9edb5c0f-bfd0-4a59-bb93-f06a52bb0128} diff --git a/windows/vs2015/povcore.vcxproj b/windows/vs2015/povcore.vcxproj index 56aaed906..9de155e14 100644 --- a/windows/vs2015/povcore.vcxproj +++ b/windows/vs2015/povcore.vcxproj @@ -464,6 +464,7 @@ + @@ -514,8 +515,10 @@ + + @@ -525,6 +528,7 @@ + @@ -553,6 +557,8 @@ + + @@ -560,6 +566,7 @@ + diff --git a/windows/vs2015/povcore.vcxproj.filters b/windows/vs2015/povcore.vcxproj.filters index 3e9736386..1f88c3857 100644 --- a/windows/vs2015/povcore.vcxproj.filters +++ b/windows/vs2015/povcore.vcxproj.filters @@ -275,6 +275,9 @@ Core Source\Math + + Core Source\Support + @@ -526,5 +529,23 @@ Core Headers\Support + + Core Headers\Scene + + + Core Headers\Support + + + Core Headers\Math + + + Core Headers\Math + + + Core Headers\Support + + + Core Headers\Support + \ No newline at end of file diff --git a/windows/vs2015/povray.sln b/windows/vs2015/povray.sln index d5f4371d4..9b3ecf49a 100644 --- a/windows/vs2015/povray.sln +++ b/windows/vs2015/povray.sln @@ -227,18 +227,12 @@ Global {C6D9B754-11EB-4FC3-8683-593BFD58C904}.Release-SSE2|Win32.Build.0 = Release-SSE2|Win32 {C6D9B754-11EB-4FC3-8683-593BFD58C904}.Release-SSE2|x64.ActiveCfg = Release|x64 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Debug|Win32.ActiveCfg = Debug|Win32 - {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Debug|Win32.Build.0 = Debug|Win32 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Debug|x64.ActiveCfg = Debug|x64 - {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Debug|x64.Build.0 = Debug|x64 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release|Win32.ActiveCfg = Release|Win32 - {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release|Win32.Build.0 = Release|Win32 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release|x64.ActiveCfg = Release|x64 - {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release|x64.Build.0 = Release|x64 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release-AVX|Win32.ActiveCfg = Release|Win32 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release-AVX|x64.ActiveCfg = Release-AVX|x64 - {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release-AVX|x64.Build.0 = Release-AVX|x64 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release-SSE2|Win32.ActiveCfg = Release-SSE2|Win32 - {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release-SSE2|Win32.Build.0 = Release-SSE2|Win32 {10B193D4-E27B-4438-A825-BFB3D2B4C74D}.Release-SSE2|x64.ActiveCfg = Release|x64 {35A2DC31-84BC-4F7A-9C93-1D072432AD79}.Debug|Win32.ActiveCfg = Debug|Win32 {35A2DC31-84BC-4F7A-9C93-1D072432AD79}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/windows/vs2015/povray.vcxproj b/windows/vs2015/povray.vcxproj index 80e1a0ea5..12f1769d3 100644 --- a/windows/vs2015/povray.vcxproj +++ b/windows/vs2015/povray.vcxproj @@ -587,9 +587,6 @@ - - {d870a978-8130-4d1d-9fb2-3ee2028d2c50} - {39c65232-04fb-4622-8283-34829739887c} false @@ -603,9 +600,6 @@ {7df42126-d237-41d3-9abe-a3acc8bac56e} - - {10b193d4-e27b-4438-a825-bfb3d2b4c74d} - {9edb5c0f-bfd0-4a59-bb93-f06a52bb0128} diff --git a/windows/winprecomp.h b/windows/winprecomp.h index 81224aa06..48b0537f7 100644 --- a/windows/winprecomp.h +++ b/windows/winprecomp.h @@ -58,7 +58,6 @@ #include // C++ standard header files -#include #include #include #include @@ -67,6 +66,7 @@ #include #include #include +#include #include #include @@ -87,13 +87,4 @@ #include // Boost header files -#include #include -#include -#include -#if POV_MULTITHREADED -#include -#include -#endif -#include -