84 static std::string get_uuid() {
85 boost::uuids::random_generator generator;
86 boost::uuids::uuid uuid = generator();
87 return boost::uuids::to_string(uuid);
95 static void wait_for(uint64_t duration_ms) {
96 std::this_thread::sleep_for(std::chrono::milliseconds(duration_ms));
99 static bool bool_equals(
bool val,
const boost::optional<bool>& opt_val) {
100 return opt_val == boost::none ? false : val == *opt_val;
107 std::string serialize(
const rapidjson::Document& doc);
108 std::string serialize(
const boost::property_tree::ptree& node);
109 void deserialize(
const std::string& json, boost::property_tree::ptree& root);
112 std::shared_ptr<T> deserialize(
const std::string& json) {
113 boost::property_tree::ptree root;
114 gen_utils::deserialize(json, root);
115 std::shared_ptr<T> obj = std::make_shared<T>();
116 T::from_property_tree(root, obj);
123 template <class T, typename std::enable_if<std::is_same<T, std::string>::value, T>::type* =
nullptr>
124 boost::optional<T> reconcile(
const boost::optional<T>& val1,
const boost::optional<T>& val2, boost::optional<bool> resolve_defined, boost::optional<bool> resolve_true, boost::optional<bool> resolve_max,
const std::string& err_msg =
"") {
127 if (val1 == val2)
return val1;
130 if (val1 == boost::none || val2 == boost::none) {
131 if (resolve_defined != boost::none && *resolve_defined ==
false)
return boost::none;
132 else return val1 == boost::none ? val2 : val1;
135 throw std::runtime_error(std::string(
"Cannot reconcile strings: ") + boost::lexical_cast<std::string>(val1) + std::string(
" vs ") + boost::lexical_cast<std::string>(val2) + (!err_msg.empty() ? std::string(
". ") + err_msg : std::string(
"")));
137 template <class T, typename std::enable_if<std::is_same<T, std::string>::value, T>::type* =
nullptr>
138 boost::optional<T> reconcile(
const boost::optional<T>& val1,
const boost::optional<T>& val2,
const std::string& err_msg =
"") {
139 return reconcile(val1, val2, boost::none, boost::none, boost::none, err_msg);
142 template <class T, typename std::enable_if<std::is_integral<T>::value, T>::type* =
nullptr>
143 boost::optional<T> reconcile(
const boost::optional<T>& val1,
const boost::optional<T>& val2, boost::optional<bool> resolve_defined, boost::optional<bool> resolve_true, boost::optional<bool> resolve_max,
const std::string& err_msg =
"") {
146 if (val1 == val2)
return val1;
149 if (val1 == boost::none || val2 == boost::none) {
150 if (resolve_defined != boost::none && *resolve_defined ==
false)
return boost::none;
151 else return val1 == boost::none ? val2 : val1;
155 if (resolve_true != boost::none)
return *val1 == *resolve_true ? val1 : val2;
158 if (resolve_max != boost::none)
return *resolve_max ? std::max(*val1, *val2) : std::min(*val1, *val2);
161 throw std::runtime_error(std::string(
"Cannot reconcile integrals: ") + boost::lexical_cast<std::string>(val1) + std::string(
" vs ") + boost::lexical_cast<std::string>(val2) + (!err_msg.empty() ? std::string(
". ") + err_msg : std::string(
"")));
163 template <class T, typename std::enable_if<std::is_integral<T>::value, T>::type* =
nullptr>
164 boost::optional<T> reconcile(
const boost::optional<T>& val1,
const boost::optional<T>& val2,
const std::string& err_msg =
"") {
165 return reconcile(val1, val2, boost::none, boost::none, boost::none, err_msg);
169 std::vector<T> reconcile(
const std::vector<T>& v1,
const std::vector<T>& v2,
const std::string& err_msg =
"") {
172 if (v1 == v2)
return v1;
175 if (v1.empty())
return v2;
176 if (v2.empty())
return v1;
179 throw std::runtime_error(
"Cannot reconcile vectors" + (!err_msg.empty() ? std::string(
". ") + err_msg : std::string(
"")));
187 class thread_poller {
190 virtual ~thread_poller();
192 bool is_polling()
const {
return m_is_polling; }
193 void set_is_polling(
bool is_polling);
194 void request_is_polling(
bool is_polling);
196 void set_period_in_ms(uint64_t period_ms) { m_poll_period_ms = period_ms; }
197 virtual void poll() = 0;
198 void wait_for_callbacks_idle();
200 class announce_scope {
202 explicit announce_scope(thread_poller& poller);
204 announce_scope(
const announce_scope&) =
delete;
205 announce_scope& operator=(
const announce_scope&) =
delete;
207 thread_poller& m_poller;
212 boost::recursive_mutex m_mutex;
213 boost::mutex m_polling_mutex;
214 boost::mutex m_lifecycle_mutex;
215 boost::thread::id m_poll_thread_id;
216 std::atomic<bool> m_is_polling;
217 bool m_poll_loop_running;
218 std::atomic<uint64_t> m_poll_period_ms;
219 boost::condition_variable m_poll_cv;
220 boost::condition_variable m_lifecycle_cv;
221 boost::mutex m_announce_mutex;
222 boost::condition_variable m_announce_cv;
223 int m_announce_count = 0;
225 void init_common(
const std::string& name);
226 void run_poll_loop();