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 <json.hpp>
17#include <mutex>
18#include <sstream>
19#include <thread>
20#include <vector>
21
22#include "skyway/global/config.hpp"
23#include "skyway/model/domain.hpp"
24
25namespace skyway {
26namespace global {
27namespace util {
28
30enum class SleepIntervalMs : int {
31 kLocal = config::kLocalSleepIntervalMs,
32 kNetwork = config::kNetworkSleepIntervalMs,
33};
34
35bool WaitUntilWithTimeoutMs(std::function<bool()> release_condition,
36 int interval_ms,
37 int timeout_ms);
38
39bool WaitUntilWithTimeoutMs(std::function<bool()> release_condition,
40 SleepIntervalMs interval,
41 int timeout_ms);
42
43bool WaitUntilWithTimeoutMs(std::atomic<bool>& release_condition_boolean,
44 int interval_ms,
45 int timeout_ms);
46
47bool WaitUntilWithTimeoutMs(std::atomic<bool>& release_condition_boolean,
48 SleepIntervalMs interval,
49 int timeout_ms);
51
57inline bool SpinLockWithTimeoutMs(std::function<bool()> release_condition, int timeout_ms) {
58 std::condition_variable cv;
59 std::mutex mtx;
60 std::unique_ptr<std::thread> observer_thread = nullptr;
61 bool is_succeeded = false;
62 {
63 std::unique_lock<std::mutex> lock(mtx);
64 // The flag used for Spurious Wakeup
65 auto is_notified = std::make_shared<bool>(false);
66 auto result_returned = std::make_shared<std::atomic<bool>>(false);
67 observer_thread = std::make_unique<std::thread>([&, result_returned, is_notified] {
68 while (!release_condition()) {
69 // Block this thread until release_condition will be true
70 if (result_returned->load()) {
71 return;
72 }
73 }
74 std::lock_guard<std::mutex> lk(mtx);
75 *is_notified = true;
76 cv.notify_one();
77 });
78 is_succeeded =
79 cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&] { return *is_notified; });
80 result_returned->store(true);
81 }
82 observer_thread->join();
83
84 return is_succeeded;
85}
86
87inline bool SpinLockWithTimeoutMs(std::atomic<bool>& release_condition, int timeout_ms) {
88 std::function<bool()> f = [&] { return release_condition.load(); };
89 return SpinLockWithTimeoutMs(f, timeout_ms);
90}
91
97inline bool SpinLockWithTimeout(std::function<bool()> release_condition,
98 int timeout_sec = config::kDefaultTimeoutSec) {
99 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
100}
101
102inline bool SpinLockWithTimeout(std::atomic<bool>& release_condition,
103 int timeout_sec = config::kDefaultTimeoutSec) {
104 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
105}
106
107inline std::string Uuid() {
108 auto id = boost::uuids::random_generator()();
109 std::string result = boost::lexical_cast<std::string>(id);
110 return result;
111}
112
113// REF:
114// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
115
121inline std::vector<std::string> Split(const std::string& s, const std::string& delimiter) {
122 size_t pos_start = 0, pos_end, delim_len = delimiter.length();
123 std::string token;
124 std::vector<std::string> res;
125
126 while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
127 token = s.substr(pos_start, pos_end - pos_start);
128 pos_start = pos_end + delim_len;
129 res.push_back(token);
130 }
131
132 res.push_back(s.substr(pos_start));
133 return res;
134}
135
136inline std::string DecodeBase64Token(const std::string& token) {
137 using InputItr = std::istreambuf_iterator<char>;
138 using OutputItr = std::ostream_iterator<char>;
139 using DecodeItr = boost::archive::iterators::
140 transform_width<boost::archive::iterators::binary_from_base64<InputItr>, 8, 6, char>;
141
142 std::stringstream input_stream, output_stream;
143 input_stream << token;
144 copy(DecodeItr(InputItr(input_stream)), DecodeItr(InputItr()), OutputItr(output_stream));
145 std::string res;
146 output_stream >> res;
147 return res;
148}
149
150inline void SetEncodingIndexToIdIfNeeded(std::vector<model::Encoding>& encodings) {
151 for (int i = 0; i < encodings.size(); i++) {
152 if (!encodings[i].id) {
153 encodings[i].id = std::to_string(i);
154 }
155 }
156}
157
158inline void SortEncodingsForMediaSoup(std::vector<model::Encoding>& encodings) {
159 if (encodings.empty()) return;
160 auto encoding = encodings[0];
161 if (encoding.max_bitrate) {
162 std::sort(encodings.begin(),
163 encodings.end(),
164 [](const model::Encoding& lhs, const model::Encoding& rhs) {
165 if (lhs.max_bitrate == std::nullopt || rhs.max_bitrate == std::nullopt) {
166 return true;
167 }
168 return *lhs.max_bitrate < *rhs.max_bitrate;
169 });
170 } else if (encoding.scale_resolution_down_by) {
171 std::sort(encodings.begin(),
172 encodings.end(),
173 [](const model::Encoding& lhs, const model::Encoding& rhs) {
174 if (lhs.scale_resolution_down_by == std::nullopt ||
175 rhs.scale_resolution_down_by == std::nullopt) {
176 return true;
177 }
178 return *lhs.scale_resolution_down_by > *rhs.scale_resolution_down_by;
179 });
180 } else if (encoding.max_framerate) {
181 std::sort(encodings.begin(),
182 encodings.end(),
183 [](const model::Encoding& lhs, const model::Encoding& rhs) {
184 if (lhs.max_framerate == std::nullopt || rhs.max_framerate == std::nullopt) {
185 return true;
186 }
187 return *lhs.max_framerate < *rhs.max_framerate;
188 });
189 }
190}
191
192inline const std::chrono::milliseconds CurrentUnixTimestampMs() {
193 return std::chrono::duration_cast<std::chrono::milliseconds>(
194 std::chrono::system_clock::now().time_since_epoch());
195}
196
197} // namespace util
198} // namespace global
199} // namespace skyway
200
201#endif /* SKYWAY_GLOBAL_UTIL_HPP_ */