-
Notifications
You must be signed in to change notification settings - Fork 14
/
file_descriptor.h
140 lines (110 loc) · 3.44 KB
/
file_descriptor.h
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
//
// Created by Xuanyi Fu on 4/15/20.
//
#ifndef XYNET_FILE_DESCRIPTOR_H
#define XYNET_FILE_DESCRIPTOR_H
#include <unistd.h>
#include <utility>
#include <xynet/detail/file_descriptor_traits.h>
#include <xynet/detail/module_list.h>
namespace xynet
{
class file_descriptor_base
{
public:
file_descriptor_base() noexcept
: m_fd{-1}
{}
explicit file_descriptor_base(int fd) noexcept : m_fd{fd} {}
file_descriptor_base(file_descriptor_base&& other)noexcept :m_fd{std::exchange(other.m_fd, -1)}{}
~file_descriptor_base(){ if(valid()){close__();}}
void set(int fd) noexcept
{
m_fd = fd;
}
[[nodiscard]] int get() const noexcept {return m_fd;}
[[nodiscard]] bool valid() const noexcept {return m_fd >= 0;}
void close__() noexcept {::close(std::exchange(m_fd, -1));}
private:
int m_fd;
};
template <typename ModuleList>
struct file_descriptor;
template <template <typename...> typename ... Modules>
class file_descriptor<detail::module_list<Modules ...>>
: public file_descriptor_base
, public Modules<file_descriptor<detail::module_list<Modules ...>>>...
{};
/* file descriptor traits */
/* get the instantiated module list from the file descriptor */
template <typename F>
struct file_descriptor_inst_module_list;
template<template <typename ...> typename... Modules>
struct file_descriptor_inst_module_list<file_descriptor<detail::module_list<Modules ...>>>
{
using type = detail::inst_module_list<Modules<void>...>;
};
/* match an inst module with a module template */
template<typename L, template <typename ...> typename R>
struct module_match : public std::false_type {};
template<typename... T, template <typename ...> typename R>
struct module_match<R<T...>, R> : public std::true_type
{};
/* find the instantiated module from an instantiated module list */
template<typename List, template <typename ...> typename Target>
struct inst_module_list_match
{
using type = void;
};
template<template <typename...> typename Target, typename Head, typename... Tails>
struct inst_module_list_match<detail::inst_module_list<Head, Tails...>, Target>
{
using type = std::conditional_t
<
module_match<Head, Target>::value,
Head,
typename inst_module_list_match<detail::inst_module_list<Tails...>, Target>::type
>;
};
template<template <typename...> typename Target>
struct inst_module_list_match<detail::inst_module_list<>, Target>
{
using type = void;
};
/* get the policy associated with a module template */
template <typename Module>
struct get_policy_from_module;
template <template <typename...> typename Module, typename T>
struct get_policy_from_module<Module<T, void>>
{
using type = T;
};
template <>
struct get_policy_from_module<void>
{
using type = void;
};
/* check if a file descriptor has a module */
template<typename FileDescriptor, template <typename ...> typename Module>
inline constexpr bool file_descriptor_has_module_v =
not std::is_same_v
<
typename inst_module_list_match
<
typename file_descriptor_inst_module_list<FileDescriptor>::type,
Module
>::type,
void
>;
/* get the policy associated with a module template in a file descriptor */
template <typename FileDescriptor, template <typename ...> typename Module>
using policy_from_file_descriptor_t =
typename get_policy_from_module
<
typename inst_module_list_match
<
typename file_descriptor_inst_module_list<FileDescriptor>::type, Module
>::type
>::type;
}
#endif //XYNET_FILE_DESCRIPTOR_H