SkyWay Linux SDK
読み取り中…
検索中…
一致する文字列を見つけられません
util.hpp
1//
2// © NTT DOCOMO BUSINESS, Inc. All Rights Reserved.
3//
4
5#ifndef SKYWAY_GLOBAL_UTIL_HPP_
6#define SKYWAY_GLOBAL_UTIL_HPP_
7
8#include <atomic>
9#include <boost/archive/iterators/binary_from_base64.hpp>
10#include <boost/archive/iterators/transform_width.hpp>
11#include <boost/lexical_cast.hpp>
12#include <boost/uuid/uuid.hpp>
13#include <boost/uuid/uuid_generators.hpp>
14#include <boost/uuid/uuid_io.hpp>
15#include <condition_variable>
16#include <functional>
17#include <json.hpp>
18#include <mutex>
19#include <sstream>
20#include <thread>
21#include <vector>
22
23#include "skyway/global/config.hpp"
24#include "skyway/model/domain.hpp"
25
26namespace skyway {
27namespace global {
28namespace util {
29
31enum class SleepIntervalMs : int {
32 kLocal = config::kLocalSleepIntervalMs,
33 kNetwork = config::kNetworkSleepIntervalMs,
34};
35
36bool WaitUntilWithTimeoutMs(std::function<bool()> release_condition,
37 int interval_ms,
38 int timeout_ms);
39
40bool WaitUntilWithTimeoutMs(std::function<bool()> release_condition,
41 SleepIntervalMs interval,
42 int timeout_ms);
43
44bool WaitUntilWithTimeoutMs(std::atomic<bool>& release_condition_boolean,
45 int interval_ms,
46 int timeout_ms);
47
48bool WaitUntilWithTimeoutMs(std::atomic<bool>& release_condition_boolean,
49 SleepIntervalMs interval,
50 int timeout_ms);
52
53class ScopeExit {
54public:
55 explicit ScopeExit(std::function<void()> on_exit) : on_exit_(on_exit) {}
56
57 ~ScopeExit() { on_exit_(); }
58
59 ScopeExit(const ScopeExit&) = delete;
60 ScopeExit& operator=(const ScopeExit&) = delete;
61
62private:
63 std::function<void()> on_exit_;
64};
65
71inline bool SpinLockWithTimeoutMs(std::function<bool()> release_condition, int timeout_ms) {
72 std::condition_variable cv;
73 std::mutex mtx;
74 std::unique_ptr<std::thread> observer_thread = nullptr;
75 bool is_succeeded = false;
76 {
77 std::unique_lock<std::mutex> lock(mtx);
78 // The flag used for Spurious Wakeup
79 auto is_notified = std::make_shared<bool>(false);
80 auto result_returned = std::make_shared<std::atomic<bool>>(false);
81 observer_thread = std::make_unique<std::thread>([&, result_returned, is_notified] {
82 while (!release_condition()) {
83 // Block this thread until release_condition will be true
84 if (result_returned->load()) {
85 return;
86 }
87 }
88 std::lock_guard<std::mutex> lk(mtx);
89 *is_notified = true;
90 cv.notify_one();
91 });
92 is_succeeded =
93 cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&] { return *is_notified; });
94 result_returned->store(true);
95 }
96 observer_thread->join();
97
98 return is_succeeded;
99}
100
101inline bool SpinLockWithTimeoutMs(std::atomic<bool>& release_condition, int timeout_ms) {
102 std::function<bool()> f = [&] { return release_condition.load(); };
103 return SpinLockWithTimeoutMs(f, timeout_ms);
104}
105
111inline bool SpinLockWithTimeout(std::function<bool()> release_condition,
112 int timeout_sec = config::kDefaultTimeoutSec) {
113 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
114}
115
116inline bool SpinLockWithTimeout(std::atomic<bool>& release_condition,
117 int timeout_sec = config::kDefaultTimeoutSec) {
118 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
119}
120
121inline std::string Uuid() {
122 auto id = boost::uuids::random_generator()();
123 std::string result = boost::lexical_cast<std::string>(id);
124 return result;
125}
126
127// REF:
128// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
129
135inline std::vector<std::string> Split(const std::string& s, const std::string& delimiter) {
136 size_t pos_start = 0, pos_end, delim_len = delimiter.length();
137 std::string token;
138 std::vector<std::string> res;
139
140 while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
141 token = s.substr(pos_start, pos_end - pos_start);
142 pos_start = pos_end + delim_len;
143 res.push_back(token);
144 }
145
146 res.push_back(s.substr(pos_start));
147 return res;
148}
149
150inline std::string DecodeBase64Token(const std::string& token) {
151 using InputItr = std::istreambuf_iterator<char>;
152 using OutputItr = std::ostream_iterator<char>;
153 using DecodeItr = boost::archive::iterators::
154 transform_width<boost::archive::iterators::binary_from_base64<InputItr>, 8, 6, char>;
155
156 std::stringstream input_stream, output_stream;
157 input_stream << token;
158 copy(DecodeItr(InputItr(input_stream)), DecodeItr(InputItr()), OutputItr(output_stream));
159 std::string res;
160 output_stream >> res;
161 return res;
162}
163
164inline void SetEncodingIndexToIdIfNeeded(std::vector<model::Encoding>& encodings) {
165 for (int i = 0; i < encodings.size(); i++) {
166 if (!encodings[i].id) {
167 encodings[i].id = std::to_string(i);
168 }
169 }
170}
171
172inline void SortEncodingsForMediaSoup(std::vector<model::Encoding>& encodings) {
173 if (encodings.empty()) return;
174 auto encoding = encodings[0];
175 if (encoding.max_bitrate) {
176 std::sort(encodings.begin(),
177 encodings.end(),
178 [](const model::Encoding& lhs, const model::Encoding& rhs) {
179 if (lhs.max_bitrate == std::nullopt || rhs.max_bitrate == std::nullopt) {
180 return true;
181 }
182 return *lhs.max_bitrate < *rhs.max_bitrate;
183 });
184 } else if (encoding.scale_resolution_down_by) {
185 std::sort(encodings.begin(),
186 encodings.end(),
187 [](const model::Encoding& lhs, const model::Encoding& rhs) {
188 if (lhs.scale_resolution_down_by == std::nullopt ||
189 rhs.scale_resolution_down_by == std::nullopt) {
190 return true;
191 }
192 return *lhs.scale_resolution_down_by > *rhs.scale_resolution_down_by;
193 });
194 } else if (encoding.max_framerate) {
195 std::sort(encodings.begin(),
196 encodings.end(),
197 [](const model::Encoding& lhs, const model::Encoding& rhs) {
198 if (lhs.max_framerate == std::nullopt || rhs.max_framerate == std::nullopt) {
199 return true;
200 }
201 return *lhs.max_framerate < *rhs.max_framerate;
202 });
203 }
204}
205
206inline const std::chrono::milliseconds CurrentUnixTimestampMs() {
207 return std::chrono::duration_cast<std::chrono::milliseconds>(
208 std::chrono::system_clock::now().time_since_epoch());
209}
210
211} // namespace util
212} // namespace global
213} // namespace skyway
214
215#endif /* SKYWAY_GLOBAL_UTIL_HPP_ */
Definition util.hpp:53