9#ifndef SKYWAY_GLOBAL_UTIL_HPP_
10#define SKYWAY_GLOBAL_UTIL_HPP_
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>
26#include "skyway/global/config.hpp"
27#include "skyway/model/domain.hpp"
38inline bool SpinLockWithTimeoutMs(std::function<
bool()> release_condition,
int timeout_ms) {
39 std::condition_variable cv;
41 std::unique_ptr<std::thread> observer_thread =
nullptr;
42 bool is_succeeded =
false;
44 std::unique_lock<std::mutex> lock(mtx);
46 bool is_notified =
false;
47 std::atomic<bool> result_returned =
false;
48 observer_thread = std::make_unique<std::thread>([&] {
49 while (!release_condition()) {
51 if (result_returned) {
55 std::lock_guard<std::mutex> lk(mtx);
60 cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&] {
return is_notified; });
61 result_returned =
true;
63 observer_thread->join();
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);
78inline bool SpinLockWithTimeout(std::function<
bool()> release_condition,
79 int timeout_sec = config::DEFAULT_TIMEOUT_SEC) {
80 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
83inline bool SpinLockWithTimeout(std::atomic<bool>& release_condition,
84 int timeout_sec = config::DEFAULT_TIMEOUT_SEC) {
85 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
88inline std::string Uuid() {
89 auto id = boost::uuids::random_generator()();
90 std::string result = boost::lexical_cast<std::string>(
id);
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();
105 std::vector<std::string> res;
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);
113 res.push_back(s.substr(pos_start));
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>;
123 std::stringstream input_stream, output_stream;
124 input_stream << token;
125 copy(DecodeItr(InputItr(input_stream)), DecodeItr(InputItr()), OutputItr(output_stream));
127 output_stream >> res;
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);
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(),
145 [](
const model::Encoding& lhs,
const model::Encoding& rhs) {
146 if (lhs.max_bitrate == boost::none || rhs.max_bitrate == boost::none) {
149 return *lhs.max_bitrate < *rhs.max_bitrate;
151 }
else if (encoding.scale_resolution_down_by) {
152 std::sort(encodings.begin(),
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) {
159 return *lhs.scale_resolution_down_by > *rhs.scale_resolution_down_by;
161 }
else if (encoding.max_framerate) {
162 std::sort(encodings.begin(),
164 [](
const model::Encoding& lhs,
const model::Encoding& rhs) {
165 if (lhs.max_framerate == boost::none || rhs.max_framerate == boost::none) {
168 return *lhs.max_framerate < *rhs.max_framerate;
173inline const std::chrono::milliseconds CurrentUnixTimestampMs() {
174 return std::chrono::duration_cast<std::chrono::milliseconds>(
175 std::chrono::system_clock::now().time_since_epoch());