Assignments
Assignments
threads.h
Go to the documentation of this file.
1/*
2Copyright (c) 2017, Michael Kazhdan
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without modification,
6are permitted provided that the following conditions are met:
7
8Redistributions of source code must retain the above copyright notice, this list of
9conditions and the following disclaimer. Redistributions in binary form must reproduce
10the above copyright notice, this list of conditions and the following disclaimer
11in the documentation and/or other materials provided with the distribution.
12
13Neither the name of the Johns Hopkins University nor the names of its contributors
14may be used to endorse or promote products derived from this software without specific
15prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26DAMAGE.
27*/
28
29#ifndef THREADS_INCLUDED
30#define THREADS_INCLUDED
31
32#include <thread>
33#include <mutex>
34#include <vector>
35#include <atomic>
36#include <condition_variable>
37#include <functional>
38#include <chrono>
39#include <future>
40#ifdef _OPENMP
41#include <omp.h>
42#endif // _OPENMP
43#include "exceptions.h"
44
45#define OLD_ATOMICS
46
47
48#ifdef OLD_ATOMICS
49#if defined( _WIN32 ) || defined( _WIN64 )
50#include <windows.h>
51#endif // _WIN32 || _WIN64
52template< typename Value >
53bool SetAtomic32( volatile Value *value , Value newValue , Value oldValue )
54{
55#if defined( _WIN32 ) || defined( _WIN64 )
56 long &_oldValue = *(long *)&oldValue;
57 long &_newValue = *(long *)&newValue;
58 return InterlockedCompareExchange( (long*)value , _newValue , _oldValue )==_oldValue;
59#else // !_WIN32 && !_WIN64
60 uint32_t &_oldValue = *(uint32_t *)&oldValue;
61 uint32_t &_newValue = *(uint32_t *)&newValue;
62 // return __sync_bool_compare_and_swap( (uint32_t *)value , _oldValue , _newValue );
63 return __atomic_compare_exchange_n( (uint32_t *)value , (uint32_t *)&oldValue , _newValue , false , __ATOMIC_SEQ_CST , __ATOMIC_SEQ_CST );
64#endif // _WIN32 || _WIN64
65}
66template< typename Value >
67bool SetAtomic64( volatile Value *value , Value newValue , Value oldValue )
68{
69#if defined( _WIN32 ) || defined( _WIN64 )
70 __int64 &_oldValue = *(__int64 *)&oldValue;
71 __int64 &_newValue = *(__int64 *)&newValue;
72 return InterlockedCompareExchange64( (__int64*)value , _newValue , _oldValue )==_oldValue;
73#else // !_WIN32 && !_WIN64
74 uint64_t &_oldValue = *(uint64_t *)&oldValue;
75 uint64_t &_newValue = *(uint64_t *)&newValue;
76 // return __sync_bool_compare_and_swap ( (uint64_t *)&value , _oldValue , _newValue );
77 return __atomic_compare_exchange_n( (uint64_t *)value , (uint64_t *)&oldValue , _newValue , false , __ATOMIC_SEQ_CST , __ATOMIC_SEQ_CST );
78#endif // _WIN32 || _WIN64
79}
80
81template< typename Value >
82bool SetAtomic( volatile Value *value , Value newValue , Value oldValue )
83{
84 switch( sizeof(Value) )
85 {
86 case 4: return SetAtomic32( value , newValue , oldValue );
87 case 8: return SetAtomic64( value , newValue , oldValue );
88 default:
89 WARN_ONCE( "should not use this function: " , sizeof(Value) );
90 static std::mutex setAtomicMutex;
91 std::lock_guard< std::mutex > lock( setAtomicMutex );
92 if( *value==oldValue ){ *value = newValue ; return true; }
93 else return false;
94 }
95}
96#endif // OLD_ATOMICS
98{
100 {
102#ifdef _OPENMP
103 OPEN_MP ,
104#endif // _OPENMP
106 ASYNC
107 };
108 static const std::vector< std::string > ParallelNames;
109
111 {
113 DYNAMIC
114 };
115 static const std::vector< std::string > ScheduleNames;
116
117 static size_t DefaultChunkSize;
119
120 template< typename ... Functions >
121 static void ParallelSections( const Functions & ... functions )
122 {
123 std::vector< std::future< void > > futures( sizeof...(Functions) );
124 _ParallelSections( &futures[0] , functions ... );
125 for( size_t t=0 ; t<futures.size() ; t++ ) futures[t].get();
126 }
127
128 static void Parallel_for( size_t begin , size_t end , const std::function< void ( unsigned int , size_t ) > &iterationFunction , ScheduleType schedule=DefaultSchedule , size_t chunkSize=DefaultChunkSize );
129
130 static unsigned int NumThreads( void );
131
132 static void Init( ParallelType parallelType , unsigned int numThreads=std::thread::hardware_concurrency() );
133
134 static void Terminate( void );
135
136private:
138 ThreadPool &operator = ( const ThreadPool & ){ return *this; }
139
140 template< typename Function >
141 static void _ParallelSections( std::future< void > *futures , const Function &function ){ *futures = std::async( std::launch::async , function ); }
142
143 template< typename Function , typename ... Functions >
144 static void _ParallelSections( std::future< void > *futures , const Function &function , const Functions& ... functions )
145 {
146 *futures = std::async( std::launch::async , function );
147 _ParallelSections( futures+1 , functions ... );
148 }
149 static inline void _ThreadInitFunction( unsigned int thread );
150
151 static bool _Close;
152#ifdef OLD_ATOMICS
153 static unsigned int _RemainingTasks;
154#else // !OLD_ATOMICS
155 static std::atomic< unsigned int > _RemainingTasks;
156#endif // OLD_ATOMICS
157 static std::mutex _Mutex;
158 static std::condition_variable _WaitingForWorkOrClose , _DoneWithWork;
159 static std::vector< std::thread > _Threads;
160 static std::function< void ( unsigned int ) > _ThreadFunction;
162};
163
164
165#endif // THREADS_INCLUDED
#define WARN_ONCE(...)
Definition: exceptions.h:148
Definition: threads.h:98
static void _ParallelSections(std::future< void > *futures, const Function &function)
Definition: threads.h:141
ThreadPool(const ThreadPool &)
Definition: threads.h:137
static bool _Close
Definition: threads.h:151
static void Terminate(void)
Definition: threads.cpp:157
static void ParallelSections(const Functions &... functions)
Definition: threads.h:121
static std::function< void(unsigned int) > _ThreadFunction
Definition: threads.h:160
static ParallelType _ParallelType
Definition: threads.h:161
static void Parallel_for(size_t begin, size_t end, const std::function< void(unsigned int, size_t) > &iterationFunction, ScheduleType schedule=DefaultSchedule, size_t chunkSize=DefaultChunkSize)
Definition: threads.cpp:58
static std::condition_variable _WaitingForWorkOrClose
Definition: threads.h:158
ParallelType
Definition: threads.h:100
@ NONE
Definition: threads.h:101
@ THREAD_POOL
Definition: threads.h:105
@ ASYNC
Definition: threads.h:106
static const std::vector< std::string > ParallelNames
Definition: threads.h:108
static size_t DefaultChunkSize
Definition: threads.h:117
static std::mutex _Mutex
Definition: threads.h:157
static void _ThreadInitFunction(unsigned int thread)
Definition: threads.cpp:168
static void _ParallelSections(std::future< void > *futures, const Function &function, const Functions &... functions)
Definition: threads.h:144
static void Init(ParallelType parallelType, unsigned int numThreads=std::thread::hardware_concurrency())
Definition: threads.cpp:138
ThreadPool & operator=(const ThreadPool &)
Definition: threads.h:138
static std::vector< std::thread > _Threads
Definition: threads.h:159
static std::condition_variable _DoneWithWork
Definition: threads.h:158
static unsigned int _RemainingTasks
Definition: threads.h:153
ScheduleType
Definition: threads.h:111
@ STATIC
Definition: threads.h:112
@ DYNAMIC
Definition: threads.h:113
static ScheduleType DefaultSchedule
Definition: threads.h:118
static const std::vector< std::string > ScheduleNames
Definition: threads.h:115
static unsigned int NumThreads(void)
Definition: threads.cpp:136
bool SetAtomic32(volatile Value *value, Value newValue, Value oldValue)
Definition: threads.h:53
bool SetAtomic64(volatile Value *value, Value newValue, Value oldValue)
Definition: threads.h:67
bool SetAtomic(volatile Value *value, Value newValue, Value oldValue)
Definition: threads.h:82