pstore2
descriptor.hpp
Go to the documentation of this file.
1 //===- include/pstore/os/descriptor.hpp -------------------*- mode: C++ -*-===//
2 //* _ _ _ *
3 //* __| | ___ ___ ___ _ __(_)_ __ | |_ ___ _ __ *
4 //* / _` |/ _ \/ __|/ __| '__| | '_ \| __/ _ \| '__| *
5 //* | (_| | __/\__ \ (__| | | | |_) | || (_) | | *
6 //* \__,_|\___||___/\___|_| |_| .__/ \__\___/|_| *
7 //* |_| *
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the pstore project, under the Apache License v2.0 with LLVM Exceptions.
11 // See https://github.com/SNSystems/pstore/blob/master/LICENSE.txt for license
12 // information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //===----------------------------------------------------------------------===//
18 #ifndef PSTORE_OS_DESCRIPTOR_HPP
19 #define PSTORE_OS_DESCRIPTOR_HPP
20 
21 #include <cerrno>
22 #include <ostream>
23 
24 #ifndef _WIN32
25 # include <netinet/in.h>
26 # include <unistd.h>
27 #else
28 # include <io.h>
29 # include <Winsock2.h>
30 using in_port_t = unsigned short;
31 #endif
32 
33 
34 namespace pstore {
35  namespace details {
36 
58  template <typename DescriptorTraits>
59  class descriptor {
60  public:
61  using value_type = typename DescriptorTraits::type;
62  using error_type = typename DescriptorTraits::error_type;
63 
64 #if defined(_WIN32) && defined(_MSC_VER)
65  // MSVC doesn't consider INVALID_HANDLE to be integral and won't allow it to be
66  // constexpr.
67  static value_type const invalid;
68  static error_type const error;
69 #else
70  static constexpr value_type invalid = DescriptorTraits::invalid;
71  static constexpr error_type error = DescriptorTraits::error;
72 #endif
73 
74  explicit constexpr descriptor (
75  DescriptorTraits const traits = DescriptorTraits ()) noexcept
76  : traits_{traits} {}
77  explicit constexpr descriptor (
78  value_type const fd, DescriptorTraits const traits = DescriptorTraits ()) noexcept
79  : fd_{fd}
80  , traits_{traits} {}
81  descriptor (descriptor && rhs) noexcept
82  : fd_{rhs.release ()}
83  , traits_{std::move (rhs.traits_)} {}
84  descriptor (descriptor const &) = delete;
85 
86  ~descriptor () {
87  auto const err = errno;
88  reset ();
89  errno = err;
90  }
91 
92  descriptor & operator= (descriptor const &) = delete;
93  descriptor & operator= (descriptor && rhs) noexcept {
94  if (this != &rhs) {
95  reset ();
96  fd_ = rhs.release ();
97  traits_ = std::move (rhs.traits_);
98  }
99  return *this;
100  }
101 
102  bool operator== (descriptor const & rhs) const noexcept { return fd_ == rhs.fd_; }
103  bool operator!= (descriptor const & rhs) const noexcept { return !operator== (rhs); }
104  bool operator< (descriptor const & rhs) const noexcept { return fd_ < rhs.fd_; }
105 
106  bool valid () const noexcept { return traits_.is_valid (fd_); }
107  value_type native_handle () const noexcept { return fd_; }
108 
109  value_type release () noexcept {
110  auto const r = fd_;
111  fd_ = invalid;
112  return r;
113  }
114 
115  void reset (value_type r = invalid) noexcept {
116  if (valid ()) {
117  traits_.close (fd_);
118  }
119  fd_ = r;
120  }
121 
122  private:
123  value_type fd_ = invalid;
124  DescriptorTraits traits_;
125  };
126 
127 #if defined(_WIN32) && defined(_MSC_VER)
128  template <typename DescriptorTraits>
129  typename descriptor<DescriptorTraits>::value_type const
130  descriptor<DescriptorTraits>::invalid = DescriptorTraits::invalid;
131 
132  template <typename DescriptorTraits>
133  typename descriptor<DescriptorTraits>::error_type const
134  descriptor<DescriptorTraits>::error = DescriptorTraits::error;
135 #endif
136 
137  template <typename DescriptorTraits>
138  inline std::ostream & operator<< (std::ostream & os,
139  descriptor<DescriptorTraits> const & fd) {
140  return os << fd.get ();
141  }
142 
143 #ifndef _WIN32
144 
145  // Not Windows.
147  public:
148  using type = int;
149  using error_type = type;
150 
151  static constexpr bool is_valid (type const fd) noexcept { return fd >= 0; }
152  static void close (type const fd) noexcept { ::close (fd); }
153 
154  static constexpr type const invalid = -1;
155  static constexpr error_type const error = -1;
156  };
159 
160 #else
161 
162  // Windows.
163  class win32_socket_descriptor_traits {
164  public:
165  using type = SOCKET;
166  using error_type = int;
167 
168  static constexpr bool is_valid (type const fd) noexcept { return fd != invalid; }
169  static void close (type const fd) noexcept { ::closesocket (fd); }
170 
171  static constexpr type const invalid = INVALID_SOCKET;
172  static constexpr error_type const error = SOCKET_ERROR;
173  };
175 
176  class win32_pipe_descriptor_traits {
177  public:
178  using type = HANDLE;
179  using error_type = type;
180 
181  static constexpr bool is_valid (type const h) noexcept { return h != invalid; }
182  static void close (type const h) noexcept { ::CloseHandle (h); }
183 
184  static type const invalid;
185  static error_type const error;
186  };
188 
189 #endif
190 
191  } // end namespace details
192 
195 #ifdef _WIN32
196  using unique_handle = pipe_descriptor;
197 #endif
198 
199 } // end namespace pstore
200 
201 namespace std {
202 
203  template <typename DescriptorTraits>
204  struct hash<pstore::details::descriptor<DescriptorTraits>> {
206  using result_type = std::size_t;
207 
208  result_type operator() (argument_type const & s) const noexcept {
209  return std::hash<typename argument_type::value_type> () (s.native_handle ());
210  }
211  };
212 
213 } // end namespace std
214 
215 #endif // PSTORE_OS_DESCRIPTOR_HPP
Definition: descriptor.hpp:146
Definition: chunked_sequence.hpp:607
Definition: print.cpp:18
DescriptorTraits is a traits structure of the following form:
Definition: descriptor.hpp:59
Definition: nonpod2.cpp:40