SkyWay for Linux
読み取り中…
検索中…
一致する文字列を見つけられません
util.hpp
1//
2// util.hpp
3// skyway
4//
5// Created by sandabu on 2021/10/14.
6// Copyright © 2021 NTT Communications. All rights reserved.
7//
8
9#ifndef SKYWAY_GLOBAL_UTIL_HPP_
10#define SKYWAY_GLOBAL_UTIL_HPP_
11
12#include <atomic>
13#include <boost/archive/iterators/binary_from_base64.hpp>
14#include <boost/archive/iterators/transform_width.hpp>
15#include <boost/lexical_cast.hpp>
16#include <boost/uuid/uuid.hpp>
17#include <boost/uuid/uuid_generators.hpp>
18#include <boost/uuid/uuid_io.hpp>
19#include <condition_variable>
20#include <json.hpp>
21#include <mutex>
22#include <sstream>
23#include <thread>
24#include <vector>
25
26#include "skyway/global/config.hpp"
27#include "skyway/model/domain.hpp"
28
29namespace skyway {
30namespace global {
31namespace util {
32
38inline bool SpinLockWithTimeoutMs(std::function<bool()> release_condition, int timeout_ms) {
39 std::condition_variable cv;
40 std::mutex mtx;
41 std::unique_ptr<std::thread> observer_thread = nullptr;
42 bool is_succeeded = false;
43 {
44 std::unique_lock<std::mutex> lock(mtx);
45 // The flag used for Spurious Wakeup
46 bool is_notified = false;
47 std::atomic<bool> result_returned = false;
48 observer_thread = std::make_unique<std::thread>([&] {
49 while (!release_condition()) {
50 // Block this thread until release_condition will be true
51 if (result_returned) {
52 return;
53 }
54 }
55 std::lock_guard<std::mutex> lk(mtx);
56 is_notified = true;
57 cv.notify_one();
58 });
59 is_succeeded =
60 cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&] { return is_notified; });
61 result_returned = true;
62 }
63 observer_thread->join();
64
65 return is_succeeded;
66}
67
68inline bool SpinLockWithTimeoutMs(std::atomic<bool>& release_condition, int timeout_ms) {
69 std::function<bool()> f = [&] { return release_condition.load(); };
70 return SpinLockWithTimeoutMs(f, timeout_ms);
71}
72
78inline bool SpinLockWithTimeout(std::function<bool()> release_condition,
79 int timeout_sec = config::DEFAULT_TIMEOUT_SEC) {
80 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
81}
82
83inline bool SpinLockWithTimeout(std::atomic<bool>& release_condition,
84 int timeout_sec = config::DEFAULT_TIMEOUT_SEC) {
85 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
86}
87
88inline std::string Uuid() {
89 auto id = boost::uuids::random_generator()();
90 std::string result = boost::lexical_cast<std::string>(id);
91 return result;
92}
93
94// REF:
95// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
96
102inline std::vector<std::string> Split(const std::string& s, const std::string& delimiter) {
103 size_t pos_start = 0, pos_end, delim_len = delimiter.length();
104 std::string token;
105 std::vector<std::string> res;
106
107 while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
108 token = s.substr(pos_start, pos_end - pos_start);
109 pos_start = pos_end + delim_len;
110 res.push_back(token);
111 }
112
113 res.push_back(s.substr(pos_start));
114 return res;
115}
116
117inline std::string DecodeBase64Token(const std::string& token) {
118 using InputItr = std::istreambuf_iterator<char>;
119 using OutputItr = std::ostream_iterator<char>;
120 using DecodeItr = boost::archive::iterators::
121 transform_width<boost::archive::iterators::binary_from_base64<InputItr>, 8, 6, char>;
122
123 std::stringstream input_stream, output_stream;
124 input_stream << token;
125 copy(DecodeItr(InputItr(input_stream)), DecodeItr(InputItr()), OutputItr(output_stream));
126 std::string res;
127 output_stream >> res;
128 return res;
129}
130
131inline void SetEncodingIndexToIdIfNeeded(std::vector<model::Encoding>& encodings) {
132 for (int i = 0; i < encodings.size(); i++) {
133 if (!encodings[i].id) {
134 encodings[i].id = std::to_string(i);
135 }
136 }
137}
138
139inline void SortEncodingsForMediaSoup(std::vector<model::Encoding>& encodings) {
140 if (encodings.empty()) return;
141 auto encoding = encodings[0];
142 if (encoding.max_bitrate) {
143 std::sort(encodings.begin(),
144 encodings.end(),
145 [](const model::Encoding& lhs, const model::Encoding& rhs) {
146 if (lhs.max_bitrate == boost::none || rhs.max_bitrate == boost::none) {
147 return true;
148 }
149 return *lhs.max_bitrate < *rhs.max_bitrate;
150 });
151 } else if (encoding.scale_resolution_down_by) {
152 std::sort(encodings.begin(),
153 encodings.end(),
154 [](const model::Encoding& lhs, const model::Encoding& rhs) {
155 if (lhs.scale_resolution_down_by == boost::none ||
156 rhs.scale_resolution_down_by == boost::none) {
157 return true;
158 }
159 return *lhs.scale_resolution_down_by > *rhs.scale_resolution_down_by;
160 });
161 } else if (encoding.max_framerate) {
162 std::sort(encodings.begin(),
163 encodings.end(),
164 [](const model::Encoding& lhs, const model::Encoding& rhs) {
165 if (lhs.max_framerate == boost::none || rhs.max_framerate == boost::none) {
166 return true;
167 }
168 return *lhs.max_framerate < *rhs.max_framerate;
169 });
170 }
171}
172
173inline const std::chrono::milliseconds CurrentUnixTimestampMs() {
174 return std::chrono::duration_cast<std::chrono::milliseconds>(
175 std::chrono::system_clock::now().time_since_epoch());
176}
177
178} // namespace util
179} // namespace global
180} // namespace skyway
181
182#endif /* SKYWAY_GLOBAL_UTIL_HPP_ */