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>
31namespace 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.
36class windows_mutex {
37 public:
38  using native_handle_type = HANDLE;
39
40  windows_mutex() { mutex_ = CreateMutex(nullptr, false, nullptr); }
41
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.
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.
57  void unlock() { ReleaseMutex(mutex_); }
58
59  // Returns the native handle for this mutex. In this case a HANDLE object.
60  native_handle_type native_handle() { return mutex_; }
61
62 private:
63  HANDLE mutex_;
64};
65
66using mutex = windows_mutex;
67}
68
69#else
70#include <pthread.h>
71#include <memory>
72namespace 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.
77class posix_mutex {
78 public:
79  using native_handle_type = pthread_mutex_t*;
80
81  posix_mutex() { pthread_mutex_init(&mutex_, nullptr); }
82
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.
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.
94  void unlock() { pthread_mutex_unlock(&mutex_); }
95
96  // Returns the native handle for this mutex. In this case a pthread_mutex_t*.
97  native_handle_type native_handle() { return &mutex_; }
98
99 private:
100  pthread_mutex_t mutex_;
101};
102
103using mutex = posix_mutex;
104}
105#endif
106
107#endif  // LIBSHADERC_UTIL_INC_MUTEX_H
108