Assignments Assignments

threads.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2017, Michael Kazhdan
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer. Redistributions in binary form must reproduce
10 the above copyright notice, this list of conditions and the following disclaimer
11 in the documentation and/or other materials provided with the distribution.
12
13 Neither the name of the Johns Hopkins University nor the names of its contributors
14 may be used to endorse or promote products derived from this software without specific
15 prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20 SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 DAMAGE.
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
52 template< typename Value >
53 bool 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}
66 template< typename Value >
67 bool 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
81 template< typename Value >
82 bool 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
97 struct ThreadPool
98{
99 enum ParallelType
100 {
101 NONE ,
102#ifdef _OPENMP
103 OPEN_MP ,
104#endif // _OPENMP
105 THREAD_POOL ,
106 ASYNC
107 };
108 static const std::vector< std::string > ParallelNames;
109
110 enum ScheduleType
111 {
112 STATIC ,
113 DYNAMIC
114 };
115 static const std::vector< std::string > ScheduleNames;
116
117 static size_t DefaultChunkSize;
118 static ScheduleType DefaultSchedule;
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
136 private:
137 ThreadPool( const ThreadPool & ){}
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;
161 static ParallelType _ParallelType;
162};
163
164
165#endif // THREADS_INCLUDED
exceptions.h
WARN_ONCE
#define WARN_ONCE(...)
Definition exceptions.h:148
ThreadPool::_ParallelSections
static void _ParallelSections(std::future< void > *futures, const Function &function)
Definition threads.h:141
ThreadPool::ThreadPool
ThreadPool(const ThreadPool &)
Definition threads.h:137
ThreadPool::_Close
static bool _Close
Definition threads.h:151
ThreadPool::Terminate
static void Terminate(void)
Definition threads.cpp:157
ThreadPool::ParallelSections
static void ParallelSections(const Functions &... functions)
Definition threads.h:121
ThreadPool::_ThreadFunction
static std::function< void(unsigned int) > _ThreadFunction
Definition threads.h:160
ThreadPool::_ParallelType
static ParallelType _ParallelType
Definition threads.h:161
ThreadPool::Parallel_for
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
ThreadPool::_WaitingForWorkOrClose
static std::condition_variable _WaitingForWorkOrClose
Definition threads.h:158
ThreadPool::ParallelType
ParallelType
Definition threads.h:100
ThreadPool::NONE
@ NONE
Definition threads.h:101
ThreadPool::THREAD_POOL
@ THREAD_POOL
Definition threads.h:105
ThreadPool::ASYNC
@ ASYNC
Definition threads.h:106
ThreadPool::ParallelNames
static const std::vector< std::string > ParallelNames
Definition threads.h:47
ThreadPool::DefaultChunkSize
static size_t DefaultChunkSize
Definition threads.h:117
ThreadPool::_Mutex
static std::mutex _Mutex
Definition threads.h:157
ThreadPool::_ThreadInitFunction
static void _ThreadInitFunction(unsigned int thread)
Definition threads.cpp:168
ThreadPool::_ParallelSections
static void _ParallelSections(std::future< void > *futures, const Function &function, const Functions &... functions)
Definition threads.h:144
ThreadPool::Init
static void Init(ParallelType parallelType, unsigned int numThreads=std::thread::hardware_concurrency())
Definition threads.cpp:138
ThreadPool::operator=
ThreadPool & operator=(const ThreadPool &)
Definition threads.h:138
ThreadPool::_Threads
static std::vector< std::thread > _Threads
Definition threads.h:159
ThreadPool::_DoneWithWork
static std::condition_variable _DoneWithWork
Definition threads.h:158
ThreadPool::_RemainingTasks
static unsigned int _RemainingTasks
Definition threads.h:153
ThreadPool::ScheduleType
ScheduleType
Definition threads.h:111
ThreadPool::STATIC
@ STATIC
Definition threads.h:112
ThreadPool::DYNAMIC
@ DYNAMIC
Definition threads.h:113
ThreadPool::DefaultSchedule
static ScheduleType DefaultSchedule
Definition threads.h:118
ThreadPool::ScheduleNames
static const std::vector< std::string > ScheduleNames
Definition threads.h:56
ThreadPool::NumThreads
static unsigned int NumThreads(void)
Definition threads.cpp:136
SetAtomic32
bool SetAtomic32(volatile Value *value, Value newValue, Value oldValue)
Definition threads.h:53
SetAtomic64
bool SetAtomic64(volatile Value *value, Value newValue, Value oldValue)
Definition threads.h:67
SetAtomic
bool SetAtomic(volatile Value *value, Value newValue, Value oldValue)
Definition threads.h:82