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
34inline bool SpinLockWithTimeoutMs(std::function<bool()> release_condition, int timeout_ms) {
35 std::condition_variable cv;
36 std::mutex mtx;
37 std::unique_ptr<std::thread> observer_thread = nullptr;
38 bool is_succeeded = false;
39 {
40 std::unique_lock<std::mutex> lock(mtx);
41 // The flag used for Spurious Wakeup
42 auto is_notified = std::make_shared<bool>(false);
43 auto result_returned = std::make_shared<std::atomic<bool>>(false);
44 observer_thread = std::make_unique<std::thread>([&, result_returned, is_notified] {
45 while (!release_condition()) {
46 // Block this thread until release_condition will be true
47 if (result_returned->load()) {
48 return;
49 }
50 }
51 std::lock_guard<std::mutex> lk(mtx);
52 *is_notified = true;
53 cv.notify_one();
54 });
55 is_succeeded =
56 cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&] { return *is_notified; });
57 result_returned->store(true);
58 }
59 observer_thread->join();
60
61 return is_succeeded;
62}
63
64inline bool SpinLockWithTimeoutMs(std::atomic<bool>& release_condition, int timeout_ms) {
65 std::function<bool()> f = [&] { return release_condition.load(); };
66 return SpinLockWithTimeoutMs(f, timeout_ms);
67}
68
74inline bool SpinLockWithTimeout(std::function<bool()> release_condition,
75 int timeout_sec = config::kDefaultTimeoutSec) {
76 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
77}
78
79inline bool SpinLockWithTimeout(std::atomic<bool>& release_condition,
80 int timeout_sec = config::kDefaultTimeoutSec) {
81 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
82}
83
84inline std::string Uuid() {
85 auto id = boost::uuids::random_generator()();
86 std::string result = boost::lexical_cast<std::string>(id);
87 return result;
88}
89
90// REF:
91// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
92
98inline std::vector<std::string> Split(const std::string& s, const std::string& delimiter) {
99 size_t pos_start = 0, pos_end, delim_len = delimiter.length();
100 std::string token;
101 std::vector<std::string> res;
102
103 while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
104 token = s.substr(pos_start, pos_end - pos_start);
105 pos_start = pos_end + delim_len;
106 res.push_back(token);
107 }
108
109 res.push_back(s.substr(pos_start));
110 return res;
111}
112
113inline std::string DecodeBase64Token(const std::string& token) {
114 using InputItr = std::istreambuf_iterator<char>;
115 using OutputItr = std::ostream_iterator<char>;
116 using DecodeItr = boost::archive::iterators::
117 transform_width<boost::archive::iterators::binary_from_base64<InputItr>, 8, 6, char>;
118
119 std::stringstream input_stream, output_stream;
120 input_stream << token;
121 copy(DecodeItr(InputItr(input_stream)), DecodeItr(InputItr()), OutputItr(output_stream));
122 std::string res;
123 output_stream >> res;
124 return res;
125}
126
127inline void SetEncodingIndexToIdIfNeeded(std::vector<model::Encoding>& encodings) {
128 for (int i = 0; i < encodings.size(); i++) {
129 if (!encodings[i].id) {
130 encodings[i].id = std::to_string(i);
131 }
132 }
133}
134
135inline void SortEncodingsForMediaSoup(std::vector<model::Encoding>& encodings) {
136 if (encodings.empty()) return;
137 auto encoding = encodings[0];
138 if (encoding.max_bitrate) {
139 std::sort(encodings.begin(),
140 encodings.end(),
141 [](const model::Encoding& lhs, const model::Encoding& rhs) {
142 if (lhs.max_bitrate == std::nullopt || rhs.max_bitrate == std::nullopt) {
143 return true;
144 }
145 return *lhs.max_bitrate < *rhs.max_bitrate;
146 });
147 } else if (encoding.scale_resolution_down_by) {
148 std::sort(encodings.begin(),
149 encodings.end(),
150 [](const model::Encoding& lhs, const model::Encoding& rhs) {
151 if (lhs.scale_resolution_down_by == std::nullopt ||
152 rhs.scale_resolution_down_by == std::nullopt) {
153 return true;
154 }
155 return *lhs.scale_resolution_down_by > *rhs.scale_resolution_down_by;
156 });
157 } else if (encoding.max_framerate) {
158 std::sort(encodings.begin(),
159 encodings.end(),
160 [](const model::Encoding& lhs, const model::Encoding& rhs) {
161 if (lhs.max_framerate == std::nullopt || rhs.max_framerate == std::nullopt) {
162 return true;
163 }
164 return *lhs.max_framerate < *rhs.max_framerate;
165 });
166 }
167}
168
169inline const std::chrono::milliseconds CurrentUnixTimestampMs() {
170 return std::chrono::duration_cast<std::chrono::milliseconds>(
171 std::chrono::system_clock::now().time_since_epoch());
172}
173
174} // namespace util
175} // namespace global
176} // namespace skyway
177
178#endif /* SKYWAY_GLOBAL_UTIL_HPP_ */