forked from google/marl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paththread.h
169 lines (131 loc) · 5.32 KB
/
thread.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
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
// Copyright 2019 The Marl Authors.
//
// 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 at
//
// https://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.
#ifndef marl_thread_h
#define marl_thread_h
#include "containers.h"
#include "export.h"
#include <functional>
namespace marl {
// Thread provides an OS abstraction for threads of execution.
class Thread {
public:
using Func = std::function<void()>;
// Core identifies a logical processor unit.
// How a core is identified varies by platform.
struct Core {
struct Windows {
uint8_t group; // Group number
uint8_t index; // Core within the processor group
};
struct Pthread {
uint16_t index; // Core number
};
union {
Windows windows;
Pthread pthread;
};
// Comparison functions
MARL_NO_EXPORT inline bool operator==(const Core&) const;
MARL_NO_EXPORT inline bool operator<(const Core&) const;
};
// Affinity holds the affinity mask for a thread - a description of what cores
// the thread is allowed to run on.
struct Affinity {
// supported is true if marl supports controlling thread affinity for this
// platform.
#if defined(_WIN32) || (defined(__linux__) && !defined(__ANDROID__)) || \
defined(__FreeBSD__)
static constexpr bool supported = true;
#else
static constexpr bool supported = false;
#endif
// Policy is an interface that provides a get() method for returning an
// Affinity for the given thread by id.
class Policy {
public:
virtual ~Policy() {}
// anyOf() returns a Policy that returns an Affinity for a number of
// available cores in affinity.
//
// Windows requires that each thread is only associated with a
// single affinity group, so the Policy's returned affinity will contain
// cores all from the same group.
MARL_EXPORT static std::shared_ptr<Policy> anyOf(
Affinity&& affinity,
Allocator* allocator = Allocator::Default);
// oneOf() returns a Policy that returns an affinity with a single enabled
// core from affinity. The single enabled core in the Policy's returned
// affinity is:
// affinity[threadId % affinity.count()]
MARL_EXPORT static std::shared_ptr<Policy> oneOf(
Affinity&& affinity,
Allocator* allocator = Allocator::Default);
// get() returns the thread Affinity for the given thread by id.
MARL_EXPORT virtual Affinity get(uint32_t threadId,
Allocator* allocator) const = 0;
};
MARL_EXPORT Affinity(Allocator*);
MARL_EXPORT Affinity(Affinity&&);
MARL_EXPORT Affinity(const Affinity&, Allocator* allocator);
// all() returns an Affinity with all the cores available to the process.
MARL_EXPORT static Affinity all(Allocator* allocator = Allocator::Default);
MARL_EXPORT Affinity(std::initializer_list<Core>, Allocator* allocator);
MARL_EXPORT Affinity(const containers::vector<Core, 32>&,
Allocator* allocator);
// count() returns the number of enabled cores in the affinity.
MARL_EXPORT size_t count() const;
// operator[] returns the i'th enabled core from this affinity.
MARL_EXPORT Core operator[](size_t index) const;
// add() adds the cores from the given affinity to this affinity.
// This affinity is returned to allow for fluent calls.
MARL_EXPORT Affinity& add(const Affinity&);
// remove() removes the cores from the given affinity from this affinity.
// This affinity is returned to allow for fluent calls.
MARL_EXPORT Affinity& remove(const Affinity&);
private:
Affinity(const Affinity&) = delete;
containers::vector<Core, 32> cores;
};
MARL_EXPORT Thread() = default;
MARL_EXPORT Thread(Thread&&);
MARL_EXPORT Thread& operator=(Thread&&);
// Start a new thread using the given affinity that calls func.
MARL_EXPORT Thread(Affinity&& affinity, Func&& func);
MARL_EXPORT ~Thread();
// join() blocks until the thread completes.
MARL_EXPORT void join();
// setName() sets the name of the currently executing thread for displaying
// in a debugger.
MARL_EXPORT static void setName(const char* fmt, ...);
// numLogicalCPUs() returns the number of available logical CPU cores for
// the system.
MARL_EXPORT static unsigned int numLogicalCPUs();
private:
Thread(const Thread&) = delete;
Thread& operator=(const Thread&) = delete;
class Impl;
Impl* impl = nullptr;
};
////////////////////////////////////////////////////////////////////////////////
// Thread::Core
////////////////////////////////////////////////////////////////////////////////
// Comparison functions
bool Thread::Core::operator==(const Core& other) const {
return pthread.index == other.pthread.index;
}
bool Thread::Core::operator<(const Core& other) const {
return pthread.index < other.pthread.index;
}
} // namespace marl
#endif // marl_thread_h