Welcome to mirror list, hosted at ThFree Co, Russian Federation.

native_handle_type.hpp « v2.0 « llfio « include - github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ccc9df4bb92d8ec438dd27c58ba0014895f5757b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* Wraps the platform specific i/o reference object
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
File Created: March 2016


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


Distributed under the Boost Software License, Version 1.0.
    (See accompanying file Licence.txt or copy at
          http://www.boost.org/LICENSE_1_0.txt)
*/

#ifndef LLFIO_CONFIG_HPP
#error You must include the master llfio.hpp, not individual header files directly
#endif
#include "config.hpp"

//! \file native_handle_type.hpp Provides native_handle_type

#ifndef LLFIO_NATIVE_HANDLE_TYPE_H
#define LLFIO_NATIVE_HANDLE_TYPE_H

LLFIO_V2_NAMESPACE_EXPORT_BEGIN

#pragma pack(push, 4)
/*! \struct native_handle_type
\brief A native handle type used for wrapping file descriptors, process ids or HANDLEs.
Unmanaged, wrap in a handle object to manage.
*/
struct native_handle_type  // NOLINT
{
  //! The type of handle.
  QUICKCPPLIB_BITFIELD_BEGIN(disposition){
  invalid = 0U,  //!< Invalid handle

  readable = 1U << 0U,     //!< Is readable
  writable = 1U << 1U,     //!< Is writable
  append_only = 1U << 2U,  //!< Is append only

  nonblocking = 1U << 4U,  //!< Requires additional synchronisation (Windows: `OVERLAPPED`; POSIX: `O_NONBLOCK`)
  seekable = 1U << 5U,     //!< Is seekable
  aligned_io = 1U << 6U,   //!< Requires sector aligned i/o (typically 512 or 4096)

  file = 1U << 8U,          //!< Is a regular file
  directory = 1U << 9U,     //!< Is a directory
  symlink = 1U << 10U,      //!< Is a symlink
  pipe = 1U << 11U,         //!< Is a pipe
  socket = 1U << 12U,       //!< Is a socket
  multiplexer = 1U << 13U,  //!< Is a kqueue/epoll/iocp
  process = 1U << 14U,      //!< Is a child process
  section = 1U << 15U,      //!< Is a memory section
  allocation = 1U << 16U,   //!< Is a memory allocation
  path = 1U << 17U,         //!< Is a path

  safety_barriers = 1U << 20U,  //!< Issue write reordering barriers at various points
  cache_metadata = 1U << 21U,   //!< Is serving metadata from the kernel cache
  cache_reads = 1U << 22U,      //!< Is serving reads from the kernel cache
  cache_writes = 1U << 23U,     //!< Is writing back from kernel cache rather than writing through
  cache_temporary = 1U << 24U,  //!< Writes are not flushed to storage quickly

  _is_connected = 1U << 28U,            // used by pipe_handle on Windows to store connectedness
  _multiplexer_state_bit0 = 1U << 29U,  // per-handle state bits used by an i/o multiplexer
  _multiplexer_state_bit1 = 1U << 30U,  // per-handle state bits used by an i/o multiplexer
  _child_close_executed = 1U << 31U     // used to trap when vptr has become corrupted
  } QUICKCPPLIB_BITFIELD_END(disposition)

  union
  {
    intptr_t _init{-1};
    //! A POSIX file descriptor
    int fd;  // NOLINT
    //! A POSIX process identifier
    int pid;  // NOLINT
    //! A Windows HANDLE
    win::handle h;  // NOLINT
    //! A third party pointer
    void *ptr;
  };
  disposition behaviour;  //! The behaviour of the handle
  //! Constructs a default instance
  constexpr native_handle_type() {}  // NOLINT
  ~native_handle_type() = default;
  //! Construct from a POSIX file descriptor
  constexpr native_handle_type(disposition _behaviour, int _fd) noexcept
      : fd(_fd)
      , behaviour(_behaviour)
  {
  }  // NOLINT
  //! Construct from a Windows HANDLE
  constexpr native_handle_type(disposition _behaviour, win::handle _h) noexcept
      : h(_h)
      , behaviour(_behaviour)
  {
  }  // NOLINT

  //! Copy construct
  native_handle_type(const native_handle_type &) = default;
  //! Move construct
  constexpr native_handle_type(native_handle_type &&o) noexcept  // NOLINT
      : _init(o._init)
      , behaviour(o.behaviour)
  {
    o.behaviour = disposition();
    o._init = -1;
  }
  //! Copy assign
  native_handle_type &operator=(const native_handle_type &) = default;
  //! Move assign
  constexpr native_handle_type &operator=(native_handle_type &&o) noexcept
  {
    if(this == &o)
    {
      return *this;
    }
    _init = o._init;
    behaviour = o.behaviour;
    o.behaviour = disposition();
    o._init = -1;
    return *this;
  }
  //! Swaps with another instance
  void swap(native_handle_type &o) noexcept
  {
    std::swap(_init, o._init);
    std::swap(behaviour, o.behaviour);
  }

  //! True if valid
  explicit constexpr operator bool() const noexcept { return is_valid(); }
  //! True if invalid
  constexpr bool operator!() const noexcept { return !is_valid(); }

  //! True if equal
  constexpr bool operator==(const native_handle_type &o) const noexcept { return behaviour == o.behaviour && _init == o._init; }
  //! True if unequal
  constexpr bool operator!=(const native_handle_type &o) const noexcept { return behaviour != o.behaviour || _init != o._init; }

  //! True if the handle is valid
  constexpr bool is_valid() const noexcept { return _init != -1 && static_cast<unsigned>(behaviour) != 0; }

  //! True if the handle is readable
  constexpr bool is_readable() const noexcept { return (behaviour & disposition::readable) ? true : false; }
  //! True if the handle is writable
  constexpr bool is_writable() const noexcept { return (behaviour & disposition::writable) ? true : false; }
  //! True if the handle is append only
  constexpr bool is_append_only() const noexcept { return (behaviour & disposition::append_only) ? true : false; }

  //! True if nonblocking
  constexpr bool is_nonblocking() const noexcept { return (behaviour & disposition::nonblocking) ? true : false; }
  //! True if seekable
  constexpr bool is_seekable() const noexcept { return (behaviour & disposition::seekable) ? true : false; }
  //! True if requires aligned i/o
  constexpr bool requires_aligned_io() const noexcept { return (behaviour & disposition::aligned_io) ? true : false; }

  //! True if a regular file or device
  constexpr bool is_regular() const noexcept { return (behaviour & disposition::file) ? true : false; }
  //! True if a directory
  constexpr bool is_directory() const noexcept { return (behaviour & disposition::directory) ? true : false; }
  //! True if a symlink
  constexpr bool is_symlink() const noexcept { return (behaviour & disposition::symlink) ? true : false; }
  //! True if a pipe
  constexpr bool is_pipe() const noexcept { return (behaviour & disposition::pipe) ? true : false; }
  //! True if a socket
  constexpr bool is_socket() const noexcept { return (behaviour & disposition::socket) ? true : false; }
  //! True if a multiplexer like BSD kqueues, Linux epoll or Windows IOCP
  constexpr bool is_multiplexer() const noexcept { return (behaviour & disposition::multiplexer) ? true : false; }
  //! True if a process
  constexpr bool is_process() const noexcept { return (behaviour & disposition::process) ? true : false; }
  //! True if a memory section
  constexpr bool is_section() const noexcept { return (behaviour & disposition::section) ? true : false; }
  //! True if a memory allocation
  constexpr bool is_allocation() const noexcept { return (behaviour & disposition::allocation) ? true : false; }
  //! True if a path or a directory
  constexpr bool is_path() const noexcept { return (behaviour & disposition::path) ? true : false; }
};
static_assert((sizeof(void *) == 4 && sizeof(native_handle_type) == 8) || (sizeof(void *) == 8 && sizeof(native_handle_type) == 12),
              "native_handle_type is not 8 or 12 bytes in size!");
// Not trivially copyable, as has non-trivial move.
static_assert(std::is_trivially_destructible<native_handle_type>::value, "native_handle_type is not trivially destructible!");
static_assert(std::is_trivially_copy_constructible<native_handle_type>::value, "native_handle_type is not trivially copy constructible!");
static_assert(std::is_trivially_copy_assignable<native_handle_type>::value, "native_handle_type is not trivially copy assignable!");

#pragma pack(pop)

LLFIO_V2_NAMESPACE_END


#endif