1 // Copyright 2015 The Shaderc Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef LIBSHADERC_UTIL_INC_MUTEX_H
16 #define LIBSHADERC_UTIL_INC_MUTEX_H
17 
18 // shaderc_util::mutex will be defined and specialized
19 // depending on the platform that is being compiled.
20 // It is more or less conformant to the C++11 specification of std::mutex.
21 // However it does not implement try_lock.
22 
23 #ifdef _WIN32
24 // windows.h #defines min and max if we don't define this.
25 // this means things like std::min and std::max break
26 #ifndef NOMINMAX
27 #define NOMINMAX
28 #endif
29 
30 #include <windows.h>
31 namespace shaderc_util {
32 
33 // As the name suggests, this mutex class is for running on windows.
34 // It conforms to the c++11 mutex implementation, and should be a
35 // drop in replacement.
36 class windows_mutex {
37  public:
38   using native_handle_type = HANDLE;
39 
windows_mutex()40   windows_mutex() { mutex_ = CreateMutex(nullptr, false, nullptr); }
41 
~windows_mutex()42   ~windows_mutex() {
43     if (mutex_ != INVALID_HANDLE_VALUE) {
44       CloseHandle(mutex_);
45     }
46   }
47 
48   windows_mutex(const windows_mutex&) = delete;
49   windows_mutex& operator=(const windows_mutex&) = delete;
50 
51   // Locks this mutex, waiting until the mutex is unlocked if it is not already.
52   // It is not valid to lock a mutex that has already been locked.
lock()53   void lock() { WaitForSingleObject(mutex_, INFINITE); }
54 
55   // Unlocks this mutex. It is invalid to unlock a mutex that this thread
56   // has not already locked.
unlock()57   void unlock() { ReleaseMutex(mutex_); }
58 
59   // Returns the native handle for this mutex. In this case a HANDLE object.
native_handle()60   native_handle_type native_handle() { return mutex_; }
61 
62  private:
63   HANDLE mutex_;
64 };
65 
66 using mutex = windows_mutex;
67 }
68 
69 #else
70 #include <pthread.h>
71 #include <memory>
72 namespace shaderc_util {
73 
74 // As the name suggests, this mutex class is for running with pthreads.
75 // It conforms to the c++11 mutex implementation, and should be a
76 // drop in replacement.
77 class posix_mutex {
78  public:
79   using native_handle_type = pthread_mutex_t*;
80 
posix_mutex()81   posix_mutex() { pthread_mutex_init(&mutex_, nullptr); }
82 
~posix_mutex()83   ~posix_mutex() { pthread_mutex_destroy(&mutex_); }
84 
85   posix_mutex(const posix_mutex&) = delete;
86   posix_mutex& operator=(const posix_mutex&) = delete;
87 
88   // Locks this mutex, waiting until the mutex is unlocked if it is not already.
89   // It is not valid to lock a mutex that has already been locked.
lock()90   void lock() { pthread_mutex_lock(&mutex_); }
91 
92   // Unlocks this mutex. It is invalid to unlock a mutex that this thread
93   // has not already locked.
unlock()94   void unlock() { pthread_mutex_unlock(&mutex_); }
95 
96   // Returns the native handle for this mutex. In this case a pthread_mutex_t*.
native_handle()97   native_handle_type native_handle() { return &mutex_; }
98 
99  private:
100   pthread_mutex_t mutex_;
101 };
102 
103 using mutex = posix_mutex;
104 }
105 #endif
106 
107 #endif  // LIBSHADERC_UTIL_INC_MUTEX_H
108