1 /* 2 * Copyright 2011-2013 Blender Foundation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef __UTIL_THREAD_H__ 18 #define __UTIL_THREAD_H__ 19 20 #include <condition_variable> 21 #include <functional> 22 #include <mutex> 23 #include <queue> 24 #include <thread> 25 26 #ifdef _WIN32 27 # include "util_windows.h" 28 #else 29 # include <pthread.h> 30 #endif 31 32 /* NOTE: Use tbb/spin_mutex.h instead of util_tbb.h because some of the TBB 33 * functionality requires RTTI, which is disabled for OSL kernel. */ 34 #include <tbb/spin_mutex.h> 35 36 #include "util/util_function.h" 37 38 CCL_NAMESPACE_BEGIN 39 40 typedef std::mutex thread_mutex; 41 typedef std::unique_lock<std::mutex> thread_scoped_lock; 42 typedef std::condition_variable thread_condition_variable; 43 44 /* Own thread implementation similar to std::thread, so we can set a 45 * custom stack size on macOS. */ 46 47 class thread { 48 public: 49 /* NOTE: Node index of -1 means that affinity will be inherited from the 50 * parent thread and no override on top of that will happen. */ 51 thread(function<void()> run_cb, int node = -1); 52 ~thread(); 53 54 static void *run(void *arg); 55 bool join(); 56 57 protected: 58 function<void()> run_cb_; 59 #ifdef __APPLE__ 60 pthread_t pthread_id; 61 #else 62 std::thread std_thread; 63 #endif 64 bool joined_; 65 int node_; 66 }; 67 68 using thread_spin_lock = tbb::spin_mutex; 69 70 class thread_scoped_spin_lock { 71 public: thread_scoped_spin_lock(thread_spin_lock & lock)72 explicit thread_scoped_spin_lock(thread_spin_lock &lock) : lock_(lock) 73 { 74 lock_.lock(); 75 } 76 ~thread_scoped_spin_lock()77 ~thread_scoped_spin_lock() 78 { 79 lock_.unlock(); 80 } 81 82 /* TODO(sergey): Implement manual control over lock/unlock. */ 83 84 protected: 85 thread_spin_lock &lock_; 86 }; 87 88 CCL_NAMESPACE_END 89 90 #endif /* __UTIL_THREAD_H__ */ 91