5#ifndef SKYWAY_GLOBAL_UTIL_HPP_
6#define SKYWAY_GLOBAL_UTIL_HPP_
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>
22#include "skyway/global/config.hpp"
23#include "skyway/model/domain.hpp"
34inline bool SpinLockWithTimeoutMs(std::function<
bool()> release_condition,
int timeout_ms) {
35 std::condition_variable cv;
37 std::unique_ptr<std::thread> observer_thread =
nullptr;
38 bool is_succeeded =
false;
40 std::unique_lock<std::mutex> lock(mtx);
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()) {
47 if (result_returned->load()) {
51 std::lock_guard<std::mutex> lk(mtx);
56 cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&] {
return *is_notified; });
57 result_returned->store(
true);
59 observer_thread->join();
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);
74inline bool SpinLockWithTimeout(std::function<
bool()> release_condition,
75 int timeout_sec = config::kDefaultTimeoutSec) {
76 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
79inline bool SpinLockWithTimeout(std::atomic<bool>& release_condition,
80 int timeout_sec = config::kDefaultTimeoutSec) {
81 return SpinLockWithTimeoutMs(release_condition, timeout_sec * 1000);
84inline std::string Uuid() {
85 auto id = boost::uuids::random_generator()();
86 std::string result = boost::lexical_cast<std::string>(
id);
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();
101 std::vector<std::string> res;
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);
109 res.push_back(s.substr(pos_start));
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>;
119 std::stringstream input_stream, output_stream;
120 input_stream << token;
121 copy(DecodeItr(InputItr(input_stream)), DecodeItr(InputItr()), OutputItr(output_stream));
123 output_stream >> res;
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);
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(),
141 [](
const model::Encoding& lhs,
const model::Encoding& rhs) {
142 if (lhs.max_bitrate == std::nullopt || rhs.max_bitrate == std::nullopt) {
145 return *lhs.max_bitrate < *rhs.max_bitrate;
147 }
else if (encoding.scale_resolution_down_by) {
148 std::sort(encodings.begin(),
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) {
155 return *lhs.scale_resolution_down_by > *rhs.scale_resolution_down_by;
157 }
else if (encoding.max_framerate) {
158 std::sort(encodings.begin(),
160 [](
const model::Encoding& lhs,
const model::Encoding& rhs) {
161 if (lhs.max_framerate == std::nullopt || rhs.max_framerate == std::nullopt) {
164 return *lhs.max_framerate < *rhs.max_framerate;
169inline const std::chrono::milliseconds CurrentUnixTimestampMs() {
170 return std::chrono::duration_cast<std::chrono::milliseconds>(
171 std::chrono::system_clock::now().time_since_epoch());