File: | include/sys/select.h |
Warning: | line 81, column 30 Array access (via field 'fds_bits') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- SelectHelper.cpp --------------------------------------------------===// | ||||||
2 | // | ||||||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||||
4 | // See https://llvm.org/LICENSE.txt for license information. | ||||||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||||
6 | // | ||||||
7 | //===----------------------------------------------------------------------===// | ||||||
8 | |||||||
9 | #if defined(__APPLE__) | ||||||
10 | // Enable this special support for Apple builds where we can have unlimited | ||||||
11 | // select bounds. We tried switching to poll() and kqueue and we were panicing | ||||||
12 | // the kernel, so we have to stick with select for now. | ||||||
13 | #define _DARWIN_UNLIMITED_SELECT | ||||||
14 | #endif | ||||||
15 | |||||||
16 | #include "lldb/Utility/SelectHelper.h" | ||||||
17 | #include "lldb/Utility/LLDBAssert.h" | ||||||
18 | #include "lldb/Utility/Status.h" | ||||||
19 | #include "lldb/lldb-enumerations.h" | ||||||
20 | #include "lldb/lldb-types.h" | ||||||
21 | |||||||
22 | #include "llvm/ADT/DenseMap.h" | ||||||
23 | #include "llvm/ADT/Optional.h" | ||||||
24 | |||||||
25 | #include <algorithm> | ||||||
26 | #include <chrono> | ||||||
27 | |||||||
28 | #include <cerrno> | ||||||
29 | #if defined(_WIN32) | ||||||
30 | // Define NOMINMAX to avoid macros that conflict with std::min and std::max | ||||||
31 | #define NOMINMAX | ||||||
32 | #include <winsock2.h> | ||||||
33 | #else | ||||||
34 | #include <sys/time.h> | ||||||
35 | #include <sys/select.h> | ||||||
36 | #endif | ||||||
37 | |||||||
38 | |||||||
39 | SelectHelper::SelectHelper() | ||||||
40 | : m_fd_map(), m_end_time() // Infinite timeout unless | ||||||
41 | // SelectHelper::SetTimeout() gets called | ||||||
42 | {} | ||||||
43 | |||||||
44 | void SelectHelper::SetTimeout(const std::chrono::microseconds &timeout) { | ||||||
45 | using namespace std::chrono; | ||||||
46 | m_end_time = steady_clock::time_point(steady_clock::now() + timeout); | ||||||
47 | } | ||||||
48 | |||||||
49 | void SelectHelper::FDSetRead(lldb::socket_t fd) { | ||||||
50 | m_fd_map[fd].read_set = true; | ||||||
51 | } | ||||||
52 | |||||||
53 | void SelectHelper::FDSetWrite(lldb::socket_t fd) { | ||||||
54 | m_fd_map[fd].write_set = true; | ||||||
55 | } | ||||||
56 | |||||||
57 | void SelectHelper::FDSetError(lldb::socket_t fd) { | ||||||
58 | m_fd_map[fd].error_set = true; | ||||||
59 | } | ||||||
60 | |||||||
61 | bool SelectHelper::FDIsSetRead(lldb::socket_t fd) const { | ||||||
62 | auto pos = m_fd_map.find(fd); | ||||||
63 | if (pos != m_fd_map.end()) | ||||||
64 | return pos->second.read_is_set; | ||||||
65 | else | ||||||
66 | return false; | ||||||
67 | } | ||||||
68 | |||||||
69 | bool SelectHelper::FDIsSetWrite(lldb::socket_t fd) const { | ||||||
70 | auto pos = m_fd_map.find(fd); | ||||||
71 | if (pos != m_fd_map.end()) | ||||||
72 | return pos->second.write_is_set; | ||||||
73 | else | ||||||
74 | return false; | ||||||
75 | } | ||||||
76 | |||||||
77 | bool SelectHelper::FDIsSetError(lldb::socket_t fd) const { | ||||||
78 | auto pos = m_fd_map.find(fd); | ||||||
79 | if (pos != m_fd_map.end()) | ||||||
80 | return pos->second.error_is_set; | ||||||
81 | else | ||||||
82 | return false; | ||||||
83 | } | ||||||
84 | |||||||
85 | static void updateMaxFd(llvm::Optional<lldb::socket_t> &vold, | ||||||
86 | lldb::socket_t vnew) { | ||||||
87 | if (!vold.hasValue()) | ||||||
88 | vold = vnew; | ||||||
89 | else | ||||||
90 | vold = std::max(*vold, vnew); | ||||||
91 | } | ||||||
92 | |||||||
93 | lldb_private::Status SelectHelper::Select() { | ||||||
94 | lldb_private::Status error; | ||||||
95 | #ifdef _WIN32 | ||||||
96 | // On windows FD_SETSIZE limits the number of file descriptors, not their | ||||||
97 | // numeric value. | ||||||
98 | lldbassert(m_fd_map.size() <= FD_SETSIZE)lldb_private::lldb_assert(static_cast<bool>(m_fd_map.size () <= 1024), "m_fd_map.size() <= FD_SETSIZE", __FUNCTION__ , "/usr/src/gnu/usr.bin/clang/liblldbUtility/../../../llvm/lldb/source/Utility/SelectHelper.cpp" , 98); | ||||||
99 | if (m_fd_map.size() > FD_SETSIZE1024) | ||||||
100 | return lldb_private::Status("Too many file descriptors for select()"); | ||||||
101 | #endif | ||||||
102 | |||||||
103 | llvm::Optional<lldb::socket_t> max_read_fd; | ||||||
104 | llvm::Optional<lldb::socket_t> max_write_fd; | ||||||
105 | llvm::Optional<lldb::socket_t> max_error_fd; | ||||||
106 | llvm::Optional<lldb::socket_t> max_fd; | ||||||
107 | for (auto &pair : m_fd_map) { | ||||||
108 | pair.second.PrepareForSelect(); | ||||||
109 | const lldb::socket_t fd = pair.first; | ||||||
110 | #if !defined(__APPLE__) && !defined(_WIN32) | ||||||
111 | lldbassert(fd < static_cast<int>(FD_SETSIZE))lldb_private::lldb_assert(static_cast<bool>(fd < static_cast <int>(1024)), "fd < static_cast<int>(FD_SETSIZE)" , __FUNCTION__, "/usr/src/gnu/usr.bin/clang/liblldbUtility/../../../llvm/lldb/source/Utility/SelectHelper.cpp" , 111); | ||||||
| |||||||
112 | if (fd
| ||||||
113 | error.SetErrorStringWithFormat("%i is too large for select()", fd); | ||||||
114 | return error; | ||||||
115 | } | ||||||
116 | #endif | ||||||
117 | if (pair.second.read_set) | ||||||
118 | updateMaxFd(max_read_fd, fd); | ||||||
119 | if (pair.second.write_set) | ||||||
120 | updateMaxFd(max_write_fd, fd); | ||||||
121 | if (pair.second.error_set) | ||||||
122 | updateMaxFd(max_error_fd, fd); | ||||||
123 | updateMaxFd(max_fd, fd); | ||||||
124 | } | ||||||
125 | |||||||
126 | if (!max_fd.hasValue()) { | ||||||
127 | error.SetErrorString("no valid file descriptors"); | ||||||
128 | return error; | ||||||
129 | } | ||||||
130 | |||||||
131 | const unsigned nfds = static_cast<unsigned>(*max_fd) + 1; | ||||||
132 | fd_set *read_fdset_ptr = nullptr; | ||||||
133 | fd_set *write_fdset_ptr = nullptr; | ||||||
134 | fd_set *error_fdset_ptr = nullptr; | ||||||
135 | // Initialize and zero out the fdsets | ||||||
136 | #if defined(__APPLE__) | ||||||
137 | llvm::SmallVector<fd_set, 1> read_fdset; | ||||||
138 | llvm::SmallVector<fd_set, 1> write_fdset; | ||||||
139 | llvm::SmallVector<fd_set, 1> error_fdset; | ||||||
140 | |||||||
141 | if (max_read_fd.hasValue()) { | ||||||
142 | read_fdset.resize((nfds / FD_SETSIZE1024) + 1); | ||||||
143 | read_fdset_ptr = read_fdset.data(); | ||||||
144 | } | ||||||
145 | if (max_write_fd.hasValue()) { | ||||||
146 | write_fdset.resize((nfds / FD_SETSIZE1024) + 1); | ||||||
147 | write_fdset_ptr = write_fdset.data(); | ||||||
148 | } | ||||||
149 | if (max_error_fd.hasValue()) { | ||||||
150 | error_fdset.resize((nfds / FD_SETSIZE1024) + 1); | ||||||
151 | error_fdset_ptr = error_fdset.data(); | ||||||
152 | } | ||||||
153 | for (auto &fd_set : read_fdset) | ||||||
154 | FD_ZERO(&fd_set)do { fd_set *_p = (&fd_set); __size_t _n = (((1024) + ((( (unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(sizeof (__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[--_n] = 0; } while (0); | ||||||
155 | for (auto &fd_set : write_fdset) | ||||||
156 | FD_ZERO(&fd_set)do { fd_set *_p = (&fd_set); __size_t _n = (((1024) + ((( (unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(sizeof (__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[--_n] = 0; } while (0); | ||||||
157 | for (auto &fd_set : error_fdset) | ||||||
158 | FD_ZERO(&fd_set)do { fd_set *_p = (&fd_set); __size_t _n = (((1024) + ((( (unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(sizeof (__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[--_n] = 0; } while (0); | ||||||
159 | #else | ||||||
160 | fd_set read_fdset; | ||||||
161 | fd_set write_fdset; | ||||||
162 | fd_set error_fdset; | ||||||
163 | |||||||
164 | if (max_read_fd.hasValue()) { | ||||||
165 | FD_ZERO(&read_fdset)do { fd_set *_p = (&read_fdset); __size_t _n = (((1024) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)( sizeof(__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[ --_n] = 0; } while (0); | ||||||
166 | read_fdset_ptr = &read_fdset; | ||||||
167 | } | ||||||
168 | if (max_write_fd.hasValue()) { | ||||||
169 | FD_ZERO(&write_fdset)do { fd_set *_p = (&write_fdset); __size_t _n = (((1024) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)( sizeof(__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[ --_n] = 0; } while (0); | ||||||
170 | write_fdset_ptr = &write_fdset; | ||||||
171 | } | ||||||
172 | if (max_error_fd.hasValue()) { | ||||||
173 | FD_ZERO(&error_fdset)do { fd_set *_p = (&error_fdset); __size_t _n = (((1024) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)( sizeof(__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[ --_n] = 0; } while (0); | ||||||
174 | error_fdset_ptr = &error_fdset; | ||||||
175 | } | ||||||
176 | #endif | ||||||
177 | // Set the FD bits in the fdsets for read/write/error | ||||||
178 | for (auto &pair : m_fd_map) { | ||||||
179 | const lldb::socket_t fd = pair.first; | ||||||
180 | |||||||
181 | if (pair.second.read_set) | ||||||
182 | FD_SET(fd, read_fdset_ptr)__fd_set((fd), (read_fdset_ptr)); | ||||||
183 | |||||||
184 | if (pair.second.write_set) | ||||||
185 | FD_SET(fd, write_fdset_ptr)__fd_set((fd), (write_fdset_ptr)); | ||||||
186 | |||||||
187 | if (pair.second.error_set) | ||||||
188 | FD_SET(fd, error_fdset_ptr)__fd_set((fd), (error_fdset_ptr)); | ||||||
189 | } | ||||||
190 | |||||||
191 | // Setup our timeout time value if needed | ||||||
192 | struct timeval *tv_ptr = nullptr; | ||||||
193 | struct timeval tv = {0, 0}; | ||||||
194 | |||||||
195 | while (true) { | ||||||
196 | using namespace std::chrono; | ||||||
197 | // Setup out relative timeout based on the end time if we have one | ||||||
198 | if (m_end_time.hasValue()) { | ||||||
199 | tv_ptr = &tv; | ||||||
200 | const auto remaining_dur = duration_cast<microseconds>( | ||||||
201 | m_end_time.getValue() - steady_clock::now()); | ||||||
202 | if (remaining_dur.count() > 0) { | ||||||
203 | // Wait for a specific amount of time | ||||||
204 | const auto dur_secs = duration_cast<seconds>(remaining_dur); | ||||||
205 | const auto dur_usecs = remaining_dur % seconds(1); | ||||||
206 | tv.tv_sec = dur_secs.count(); | ||||||
207 | tv.tv_usec = dur_usecs.count(); | ||||||
208 | } else { | ||||||
209 | // Just poll once with no timeout | ||||||
210 | tv.tv_sec = 0; | ||||||
211 | tv.tv_usec = 0; | ||||||
212 | } | ||||||
213 | } | ||||||
214 | const int num_set_fds = ::select(nfds, read_fdset_ptr, write_fdset_ptr, | ||||||
215 | error_fdset_ptr, tv_ptr); | ||||||
216 | if (num_set_fds < 0) { | ||||||
217 | // We got an error | ||||||
218 | error.SetErrorToErrno(); | ||||||
219 | if (error.GetError() == EINTR4) { | ||||||
220 | error.Clear(); | ||||||
221 | continue; // Keep calling select if we get EINTR | ||||||
222 | } else | ||||||
223 | return error; | ||||||
224 | } else if (num_set_fds == 0) { | ||||||
225 | // Timeout | ||||||
226 | error.SetError(ETIMEDOUT60, lldb::eErrorTypePOSIX); | ||||||
227 | error.SetErrorString("timed out"); | ||||||
228 | return error; | ||||||
229 | } else { | ||||||
230 | // One or more descriptors were set, update the FDInfo::select_is_set | ||||||
231 | // mask so users can ask the SelectHelper class so clients can call one | ||||||
232 | // of: | ||||||
233 | |||||||
234 | for (auto &pair : m_fd_map) { | ||||||
235 | const int fd = pair.first; | ||||||
236 | |||||||
237 | if (pair.second.read_set) { | ||||||
238 | if (FD_ISSET(fd, read_fdset_ptr)__fd_isset((fd), (read_fdset_ptr))) | ||||||
239 | pair.second.read_is_set = true; | ||||||
240 | } | ||||||
241 | if (pair.second.write_set) { | ||||||
242 | if (FD_ISSET(fd, write_fdset_ptr)__fd_isset((fd), (write_fdset_ptr))) | ||||||
243 | pair.second.write_is_set = true; | ||||||
244 | } | ||||||
245 | if (pair.second.error_set) { | ||||||
246 | if (FD_ISSET(fd, error_fdset_ptr)__fd_isset((fd), (error_fdset_ptr))) | ||||||
247 | pair.second.error_is_set = true; | ||||||
248 | } | ||||||
249 | } | ||||||
250 | break; | ||||||
251 | } | ||||||
252 | } | ||||||
253 | return error; | ||||||
254 | } |
1 | //===- Optional.h - Simple variant for passing optional values --*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file provides Optional, a template class modeled in the spirit of |
10 | // OCaml's 'opt' variant. The idea is to strongly type whether or not |
11 | // a value can be optional. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_ADT_OPTIONAL_H |
16 | #define LLVM_ADT_OPTIONAL_H |
17 | |
18 | #include "llvm/ADT/Hashing.h" |
19 | #include "llvm/ADT/None.h" |
20 | #include "llvm/ADT/STLForwardCompat.h" |
21 | #include "llvm/Support/Compiler.h" |
22 | #include "llvm/Support/type_traits.h" |
23 | #include <cassert> |
24 | #include <memory> |
25 | #include <new> |
26 | #include <utility> |
27 | |
28 | namespace llvm { |
29 | |
30 | class raw_ostream; |
31 | |
32 | namespace optional_detail { |
33 | |
34 | /// Storage for any type. |
35 | // |
36 | // The specialization condition intentionally uses |
37 | // llvm::is_trivially_copy_constructible instead of |
38 | // std::is_trivially_copy_constructible. GCC versions prior to 7.4 may |
39 | // instantiate the copy constructor of `T` when |
40 | // std::is_trivially_copy_constructible is instantiated. This causes |
41 | // compilation to fail if we query the trivially copy constructible property of |
42 | // a class which is not copy constructible. |
43 | // |
44 | // The current implementation of OptionalStorage insists that in order to use |
45 | // the trivial specialization, the value_type must be trivially copy |
46 | // constructible and trivially copy assignable due to =default implementations |
47 | // of the copy/move constructor/assignment. It does not follow that this is |
48 | // necessarily the case std::is_trivially_copyable is true (hence the expanded |
49 | // specialization condition). |
50 | // |
51 | // The move constructible / assignable conditions emulate the remaining behavior |
52 | // of std::is_trivially_copyable. |
53 | template <typename T, bool = (llvm::is_trivially_copy_constructible<T>::value && |
54 | std::is_trivially_copy_assignable<T>::value && |
55 | (std::is_trivially_move_constructible<T>::value || |
56 | !std::is_move_constructible<T>::value) && |
57 | (std::is_trivially_move_assignable<T>::value || |
58 | !std::is_move_assignable<T>::value))> |
59 | class OptionalStorage { |
60 | union { |
61 | char empty; |
62 | T value; |
63 | }; |
64 | bool hasVal; |
65 | |
66 | public: |
67 | ~OptionalStorage() { reset(); } |
68 | |
69 | constexpr OptionalStorage() noexcept : empty(), hasVal(false) {} |
70 | |
71 | constexpr OptionalStorage(OptionalStorage const &other) : OptionalStorage() { |
72 | if (other.hasValue()) { |
73 | emplace(other.value); |
74 | } |
75 | } |
76 | constexpr OptionalStorage(OptionalStorage &&other) : OptionalStorage() { |
77 | if (other.hasValue()) { |
78 | emplace(std::move(other.value)); |
79 | } |
80 | } |
81 | |
82 | template <class... Args> |
83 | constexpr explicit OptionalStorage(in_place_t, Args &&... args) |
84 | : value(std::forward<Args>(args)...), hasVal(true) {} |
85 | |
86 | void reset() noexcept { |
87 | if (hasVal) { |
88 | value.~T(); |
89 | hasVal = false; |
90 | } |
91 | } |
92 | |
93 | constexpr bool hasValue() const noexcept { return hasVal; } |
94 | |
95 | T &getValue() LLVM_LVALUE_FUNCTION& noexcept { |
96 | assert(hasVal)((void)0); |
97 | return value; |
98 | } |
99 | constexpr T const &getValue() const LLVM_LVALUE_FUNCTION& noexcept { |
100 | assert(hasVal)((void)0); |
101 | return value; |
102 | } |
103 | #if LLVM_HAS_RVALUE_REFERENCE_THIS1 |
104 | T &&getValue() && noexcept { |
105 | assert(hasVal)((void)0); |
106 | return std::move(value); |
107 | } |
108 | #endif |
109 | |
110 | template <class... Args> void emplace(Args &&... args) { |
111 | reset(); |
112 | ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...); |
113 | hasVal = true; |
114 | } |
115 | |
116 | OptionalStorage &operator=(T const &y) { |
117 | if (hasValue()) { |
118 | value = y; |
119 | } else { |
120 | ::new ((void *)std::addressof(value)) T(y); |
121 | hasVal = true; |
122 | } |
123 | return *this; |
124 | } |
125 | OptionalStorage &operator=(T &&y) { |
126 | if (hasValue()) { |
127 | value = std::move(y); |
128 | } else { |
129 | ::new ((void *)std::addressof(value)) T(std::move(y)); |
130 | hasVal = true; |
131 | } |
132 | return *this; |
133 | } |
134 | |
135 | OptionalStorage &operator=(OptionalStorage const &other) { |
136 | if (other.hasValue()) { |
137 | if (hasValue()) { |
138 | value = other.value; |
139 | } else { |
140 | ::new ((void *)std::addressof(value)) T(other.value); |
141 | hasVal = true; |
142 | } |
143 | } else { |
144 | reset(); |
145 | } |
146 | return *this; |
147 | } |
148 | |
149 | OptionalStorage &operator=(OptionalStorage &&other) { |
150 | if (other.hasValue()) { |
151 | if (hasValue()) { |
152 | value = std::move(other.value); |
153 | } else { |
154 | ::new ((void *)std::addressof(value)) T(std::move(other.value)); |
155 | hasVal = true; |
156 | } |
157 | } else { |
158 | reset(); |
159 | } |
160 | return *this; |
161 | } |
162 | }; |
163 | |
164 | template <typename T> class OptionalStorage<T, true> { |
165 | union { |
166 | char empty; |
167 | T value; |
168 | }; |
169 | bool hasVal = false; |
170 | |
171 | public: |
172 | ~OptionalStorage() = default; |
173 | |
174 | constexpr OptionalStorage() noexcept : empty{} {} |
175 | |
176 | constexpr OptionalStorage(OptionalStorage const &other) = default; |
177 | constexpr OptionalStorage(OptionalStorage &&other) = default; |
178 | |
179 | OptionalStorage &operator=(OptionalStorage const &other) = default; |
180 | OptionalStorage &operator=(OptionalStorage &&other) = default; |
181 | |
182 | template <class... Args> |
183 | constexpr explicit OptionalStorage(in_place_t, Args &&... args) |
184 | : value(std::forward<Args>(args)...), hasVal(true) {} |
185 | |
186 | void reset() noexcept { |
187 | if (hasVal) { |
188 | value.~T(); |
189 | hasVal = false; |
190 | } |
191 | } |
192 | |
193 | constexpr bool hasValue() const noexcept { return hasVal; } |
194 | |
195 | T &getValue() LLVM_LVALUE_FUNCTION& noexcept { |
196 | assert(hasVal)((void)0); |
197 | return value; |
198 | } |
199 | constexpr T const &getValue() const LLVM_LVALUE_FUNCTION& noexcept { |
200 | assert(hasVal)((void)0); |
201 | return value; |
202 | } |
203 | #if LLVM_HAS_RVALUE_REFERENCE_THIS1 |
204 | T &&getValue() && noexcept { |
205 | assert(hasVal)((void)0); |
206 | return std::move(value); |
207 | } |
208 | #endif |
209 | |
210 | template <class... Args> void emplace(Args &&... args) { |
211 | reset(); |
212 | ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...); |
213 | hasVal = true; |
214 | } |
215 | |
216 | OptionalStorage &operator=(T const &y) { |
217 | if (hasValue()) { |
218 | value = y; |
219 | } else { |
220 | ::new ((void *)std::addressof(value)) T(y); |
221 | hasVal = true; |
222 | } |
223 | return *this; |
224 | } |
225 | OptionalStorage &operator=(T &&y) { |
226 | if (hasValue()) { |
227 | value = std::move(y); |
228 | } else { |
229 | ::new ((void *)std::addressof(value)) T(std::move(y)); |
230 | hasVal = true; |
231 | } |
232 | return *this; |
233 | } |
234 | }; |
235 | |
236 | } // namespace optional_detail |
237 | |
238 | template <typename T> class Optional { |
239 | optional_detail::OptionalStorage<T> Storage; |
240 | |
241 | public: |
242 | using value_type = T; |
243 | |
244 | constexpr Optional() {} |
245 | constexpr Optional(NoneType) {} |
246 | |
247 | constexpr Optional(const T &y) : Storage(in_place, y) {} |
248 | constexpr Optional(const Optional &O) = default; |
249 | |
250 | constexpr Optional(T &&y) : Storage(in_place, std::move(y)) {} |
251 | constexpr Optional(Optional &&O) = default; |
252 | |
253 | template <typename... ArgTypes> |
254 | constexpr Optional(in_place_t, ArgTypes &&...Args) |
255 | : Storage(in_place, std::forward<ArgTypes>(Args)...) {} |
256 | |
257 | Optional &operator=(T &&y) { |
258 | Storage = std::move(y); |
259 | return *this; |
260 | } |
261 | Optional &operator=(Optional &&O) = default; |
262 | |
263 | /// Create a new object by constructing it in place with the given arguments. |
264 | template <typename... ArgTypes> void emplace(ArgTypes &&... Args) { |
265 | Storage.emplace(std::forward<ArgTypes>(Args)...); |
266 | } |
267 | |
268 | static constexpr Optional create(const T *y) { |
269 | return y ? Optional(*y) : Optional(); |
270 | } |
271 | |
272 | Optional &operator=(const T &y) { |
273 | Storage = y; |
274 | return *this; |
275 | } |
276 | Optional &operator=(const Optional &O) = default; |
277 | |
278 | void reset() { Storage.reset(); } |
279 | |
280 | constexpr const T *getPointer() const { return &Storage.getValue(); } |
281 | T *getPointer() { return &Storage.getValue(); } |
282 | constexpr const T &getValue() const LLVM_LVALUE_FUNCTION& { |
283 | return Storage.getValue(); |
284 | } |
285 | T &getValue() LLVM_LVALUE_FUNCTION& { return Storage.getValue(); } |
286 | |
287 | constexpr explicit operator bool() const { return hasValue(); } |
288 | constexpr bool hasValue() const { return Storage.hasValue(); } |
289 | constexpr const T *operator->() const { return getPointer(); } |
290 | T *operator->() { return getPointer(); } |
291 | constexpr const T &operator*() const LLVM_LVALUE_FUNCTION& { |
292 | return getValue(); |
293 | } |
294 | T &operator*() LLVM_LVALUE_FUNCTION& { return getValue(); } |
295 | |
296 | template <typename U> |
297 | constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION& { |
298 | return hasValue() ? getValue() : std::forward<U>(value); |
299 | } |
300 | |
301 | /// Apply a function to the value if present; otherwise return None. |
302 | template <class Function> |
303 | auto map(const Function &F) const LLVM_LVALUE_FUNCTION& |
304 | -> Optional<decltype(F(getValue()))> { |
305 | if (*this) return F(getValue()); |
306 | return None; |
307 | } |
308 | |
309 | #if LLVM_HAS_RVALUE_REFERENCE_THIS1 |
310 | T &&getValue() && { return std::move(Storage.getValue()); } |
311 | T &&operator*() && { return std::move(Storage.getValue()); } |
312 | |
313 | template <typename U> |
314 | T getValueOr(U &&value) && { |
315 | return hasValue() ? std::move(getValue()) : std::forward<U>(value); |
316 | } |
317 | |
318 | /// Apply a function to the value if present; otherwise return None. |
319 | template <class Function> |
320 | auto map(const Function &F) && |
321 | -> Optional<decltype(F(std::move(*this).getValue()))> { |
322 | if (*this) return F(std::move(*this).getValue()); |
323 | return None; |
324 | } |
325 | #endif |
326 | }; |
327 | |
328 | template <class T> llvm::hash_code hash_value(const Optional<T> &O) { |
329 | return O ? hash_combine(true, *O) : hash_value(false); |
330 | } |
331 | |
332 | template <typename T, typename U> |
333 | constexpr bool operator==(const Optional<T> &X, const Optional<U> &Y) { |
334 | if (X && Y) |
335 | return *X == *Y; |
336 | return X.hasValue() == Y.hasValue(); |
337 | } |
338 | |
339 | template <typename T, typename U> |
340 | constexpr bool operator!=(const Optional<T> &X, const Optional<U> &Y) { |
341 | return !(X == Y); |
342 | } |
343 | |
344 | template <typename T, typename U> |
345 | constexpr bool operator<(const Optional<T> &X, const Optional<U> &Y) { |
346 | if (X && Y) |
347 | return *X < *Y; |
348 | return X.hasValue() < Y.hasValue(); |
349 | } |
350 | |
351 | template <typename T, typename U> |
352 | constexpr bool operator<=(const Optional<T> &X, const Optional<U> &Y) { |
353 | return !(Y < X); |
354 | } |
355 | |
356 | template <typename T, typename U> |
357 | constexpr bool operator>(const Optional<T> &X, const Optional<U> &Y) { |
358 | return Y < X; |
359 | } |
360 | |
361 | template <typename T, typename U> |
362 | constexpr bool operator>=(const Optional<T> &X, const Optional<U> &Y) { |
363 | return !(X < Y); |
364 | } |
365 | |
366 | template <typename T> |
367 | constexpr bool operator==(const Optional<T> &X, NoneType) { |
368 | return !X; |
369 | } |
370 | |
371 | template <typename T> |
372 | constexpr bool operator==(NoneType, const Optional<T> &X) { |
373 | return X == None; |
374 | } |
375 | |
376 | template <typename T> |
377 | constexpr bool operator!=(const Optional<T> &X, NoneType) { |
378 | return !(X == None); |
379 | } |
380 | |
381 | template <typename T> |
382 | constexpr bool operator!=(NoneType, const Optional<T> &X) { |
383 | return X != None; |
384 | } |
385 | |
386 | template <typename T> constexpr bool operator<(const Optional<T> &, NoneType) { |
387 | return false; |
388 | } |
389 | |
390 | template <typename T> constexpr bool operator<(NoneType, const Optional<T> &X) { |
391 | return X.hasValue(); |
392 | } |
393 | |
394 | template <typename T> |
395 | constexpr bool operator<=(const Optional<T> &X, NoneType) { |
396 | return !(None < X); |
397 | } |
398 | |
399 | template <typename T> |
400 | constexpr bool operator<=(NoneType, const Optional<T> &X) { |
401 | return !(X < None); |
402 | } |
403 | |
404 | template <typename T> constexpr bool operator>(const Optional<T> &X, NoneType) { |
405 | return None < X; |
406 | } |
407 | |
408 | template <typename T> constexpr bool operator>(NoneType, const Optional<T> &X) { |
409 | return X < None; |
410 | } |
411 | |
412 | template <typename T> |
413 | constexpr bool operator>=(const Optional<T> &X, NoneType) { |
414 | return None <= X; |
415 | } |
416 | |
417 | template <typename T> |
418 | constexpr bool operator>=(NoneType, const Optional<T> &X) { |
419 | return X <= None; |
420 | } |
421 | |
422 | template <typename T> |
423 | constexpr bool operator==(const Optional<T> &X, const T &Y) { |
424 | return X && *X == Y; |
425 | } |
426 | |
427 | template <typename T> |
428 | constexpr bool operator==(const T &X, const Optional<T> &Y) { |
429 | return Y && X == *Y; |
430 | } |
431 | |
432 | template <typename T> |
433 | constexpr bool operator!=(const Optional<T> &X, const T &Y) { |
434 | return !(X == Y); |
435 | } |
436 | |
437 | template <typename T> |
438 | constexpr bool operator!=(const T &X, const Optional<T> &Y) { |
439 | return !(X == Y); |
440 | } |
441 | |
442 | template <typename T> |
443 | constexpr bool operator<(const Optional<T> &X, const T &Y) { |
444 | return !X || *X < Y; |
445 | } |
446 | |
447 | template <typename T> |
448 | constexpr bool operator<(const T &X, const Optional<T> &Y) { |
449 | return Y && X < *Y; |
450 | } |
451 | |
452 | template <typename T> |
453 | constexpr bool operator<=(const Optional<T> &X, const T &Y) { |
454 | return !(Y < X); |
455 | } |
456 | |
457 | template <typename T> |
458 | constexpr bool operator<=(const T &X, const Optional<T> &Y) { |
459 | return !(Y < X); |
460 | } |
461 | |
462 | template <typename T> |
463 | constexpr bool operator>(const Optional<T> &X, const T &Y) { |
464 | return Y < X; |
465 | } |
466 | |
467 | template <typename T> |
468 | constexpr bool operator>(const T &X, const Optional<T> &Y) { |
469 | return Y < X; |
470 | } |
471 | |
472 | template <typename T> |
473 | constexpr bool operator>=(const Optional<T> &X, const T &Y) { |
474 | return !(X < Y); |
475 | } |
476 | |
477 | template <typename T> |
478 | constexpr bool operator>=(const T &X, const Optional<T> &Y) { |
479 | return !(X < Y); |
480 | } |
481 | |
482 | raw_ostream &operator<<(raw_ostream &OS, NoneType); |
483 | |
484 | template <typename T, typename = decltype(std::declval<raw_ostream &>() |
485 | << std::declval<const T &>())> |
486 | raw_ostream &operator<<(raw_ostream &OS, const Optional<T> &O) { |
487 | if (O) |
488 | OS << *O; |
489 | else |
490 | OS << None; |
491 | return OS; |
492 | } |
493 | |
494 | } // end namespace llvm |
495 | |
496 | #endif // LLVM_ADT_OPTIONAL_H |
1 | /* $OpenBSD: select.h,v 1.17 2016/09/12 19:41:20 guenther Exp $ */ | |||
2 | ||||
3 | /*- | |||
4 | * Copyright (c) 1992, 1993 | |||
5 | * The Regents of the University of California. All rights reserved. | |||
6 | * | |||
7 | * Redistribution and use in source and binary forms, with or without | |||
8 | * modification, are permitted provided that the following conditions | |||
9 | * are met: | |||
10 | * 1. Redistributions of source code must retain the above copyright | |||
11 | * notice, this list of conditions and the following disclaimer. | |||
12 | * 2. Redistributions in binary form must reproduce the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer in the | |||
14 | * documentation and/or other materials provided with the distribution. | |||
15 | * 3. Neither the name of the University nor the names of its contributors | |||
16 | * may be used to endorse or promote products derived from this software | |||
17 | * without specific prior written permission. | |||
18 | * | |||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
29 | * SUCH DAMAGE. | |||
30 | * | |||
31 | * @(#)select.h 8.2 (Berkeley) 1/4/94 | |||
32 | */ | |||
33 | ||||
34 | #ifndef _SYS_SELECT_H_ | |||
35 | #define _SYS_SELECT_H_ | |||
36 | ||||
37 | #include <sys/types.h> | |||
38 | ||||
39 | #ifndef _TIMEVAL_DECLARED | |||
40 | #define _TIMEVAL_DECLARED | |||
41 | struct timeval { | |||
42 | time_t tv_sec; /* seconds */ | |||
43 | suseconds_t tv_usec; /* and microseconds */ | |||
44 | }; | |||
45 | #endif | |||
46 | ||||
47 | #ifndef _TIMESPEC_DECLARED | |||
48 | #define _TIMESPEC_DECLARED | |||
49 | struct timespec { | |||
50 | time_t tv_sec; /* seconds */ | |||
51 | long tv_nsec; /* and nanoseconds */ | |||
52 | }; | |||
53 | #endif | |||
54 | ||||
55 | /* | |||
56 | * Select uses bit masks of file descriptors in longs. These macros | |||
57 | * manipulate such bit fields (the filesystem macros use chars). | |||
58 | * FD_SETSIZE may be defined by the user, but the default here should | |||
59 | * be enough for most uses. | |||
60 | */ | |||
61 | #ifndef FD_SETSIZE1024 | |||
62 | #define FD_SETSIZE1024 1024 | |||
63 | #endif | |||
64 | ||||
65 | /* | |||
66 | * We don't want to pollute the namespace with select(2) internals. | |||
67 | * Non-underscore versions are exposed later #if __BSD_VISIBLE | |||
68 | */ | |||
69 | #define __NBBY8 8 /* number of bits in a byte */ | |||
70 | typedef uint32_t __fd_mask; | |||
71 | #define __NFDBITS((unsigned)(sizeof(__fd_mask) * 8)) ((unsigned)(sizeof(__fd_mask) * __NBBY8)) /* bits per mask */ | |||
72 | #define __howmany(x, y)(((x) + ((y) - 1)) / (y)) (((x) + ((y) - 1)) / (y)) | |||
73 | ||||
74 | typedef struct fd_set { | |||
75 | __fd_mask fds_bits[__howmany(FD_SETSIZE, __NFDBITS)(((1024) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / ((( unsigned)(sizeof(__fd_mask) * 8))))]; | |||
76 | } fd_set; | |||
77 | ||||
78 | static __inlineinline void | |||
79 | __fd_set(int fd, fd_set *p) | |||
80 | { | |||
81 | p->fds_bits[fd / __NFDBITS((unsigned)(sizeof(__fd_mask) * 8))] |= (1U << (fd % __NFDBITS((unsigned)(sizeof(__fd_mask) * 8)))); | |||
| ||||
82 | } | |||
83 | #define FD_SET(n, p)__fd_set((n), (p)) __fd_set((n), (p)) | |||
84 | ||||
85 | static __inlineinline void | |||
86 | __fd_clr(int fd, fd_set *p) | |||
87 | { | |||
88 | p->fds_bits[fd / __NFDBITS((unsigned)(sizeof(__fd_mask) * 8))] &= ~(1U << (fd % __NFDBITS((unsigned)(sizeof(__fd_mask) * 8)))); | |||
89 | } | |||
90 | #define FD_CLR(n, p)__fd_clr((n), (p)) __fd_clr((n), (p)) | |||
91 | ||||
92 | static __inlineinline int | |||
93 | __fd_isset(int fd, const fd_set *p) | |||
94 | { | |||
95 | return (p->fds_bits[fd / __NFDBITS((unsigned)(sizeof(__fd_mask) * 8))] & (1U << (fd % __NFDBITS((unsigned)(sizeof(__fd_mask) * 8))))); | |||
96 | } | |||
97 | #define FD_ISSET(n, p)__fd_isset((n), (p)) __fd_isset((n), (p)) | |||
98 | ||||
99 | #if __BSD_VISIBLE1 | |||
100 | #define FD_COPY(f, t)(void)(*(t) = *(f)) (void)(*(t) = *(f)) | |||
101 | #endif | |||
102 | #define FD_ZERO(p)do { fd_set *_p = (p); __size_t _n = (((1024) + ((((unsigned) (sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(sizeof(__fd_mask ) * 8)))); while (_n > 0) _p->fds_bits[--_n] = 0; } while (0) do { \ | |||
103 | fd_set *_p = (p); \ | |||
104 | __size_t _n = __howmany(FD_SETSIZE, __NFDBITS)(((1024) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / ((( unsigned)(sizeof(__fd_mask) * 8)))); \ | |||
105 | \ | |||
106 | while (_n > 0) \ | |||
107 | _p->fds_bits[--_n] = 0; \ | |||
108 | } while (0) | |||
109 | ||||
110 | #if __BSD_VISIBLE1 | |||
111 | #define NBBY8 __NBBY8 | |||
112 | #define fd_mask__fd_mask __fd_mask | |||
113 | #define NFDBITS((unsigned)(sizeof(__fd_mask) * 8)) __NFDBITS((unsigned)(sizeof(__fd_mask) * 8)) | |||
114 | #ifndef howmany | |||
115 | #define howmany(x, y)(((x) + ((y) - 1)) / (y)) __howmany(x, y)(((x) + ((y) - 1)) / (y)) | |||
116 | #endif | |||
117 | #endif /* __BSD_VISIBLE */ | |||
118 | ||||
119 | #ifndef _KERNEL | |||
120 | #ifndef _SIGSET_T_DEFINED_ | |||
121 | #define _SIGSET_T_DEFINED_ | |||
122 | typedef unsigned int sigset_t; | |||
123 | #endif | |||
124 | ||||
125 | #ifndef _SELECT_DEFINED_ | |||
126 | #define _SELECT_DEFINED_ | |||
127 | __BEGIN_DECLSextern "C" { | |||
128 | int select(int, fd_set * __restrict, fd_set * __restrict, | |||
129 | fd_set * __restrict, struct timeval * __restrict); | |||
130 | int pselect(int, fd_set * __restrict, fd_set * __restrict, | |||
131 | fd_set * __restrict, const struct timespec * __restrict, | |||
132 | const sigset_t * __restrict); | |||
133 | __END_DECLS} | |||
134 | #endif | |||
135 | #endif /* !_KERNEL */ | |||
136 | ||||
137 | #endif /* !_SYS_SELECT_H_ */ |