Update in-tree libosmium dependency to 2.5.4
The latest releases have some critical fixes, see the changelog: https://github.com/osmcode/libosmium/blob/v2.5.4/CHANGELOG.md Merge commit 'afdf8e7b21fbaf597e91d9d8a7542635e60ee9a1' into use_libosmium_2_5_4
This commit is contained in:
@@ -50,7 +50,9 @@ namespace osmium {
|
||||
struct impl_base {
|
||||
|
||||
virtual ~impl_base() = default;
|
||||
virtual void call() = 0;
|
||||
virtual bool call() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // struct impl_base
|
||||
|
||||
@@ -58,28 +60,38 @@ namespace osmium {
|
||||
|
||||
template <typename F>
|
||||
struct impl_type : impl_base {
|
||||
|
||||
F m_functor;
|
||||
|
||||
impl_type(F&& functor) :
|
||||
m_functor(std::move(functor)) {
|
||||
explicit impl_type(F&& functor) :
|
||||
m_functor(std::forward<F>(functor)) {
|
||||
}
|
||||
|
||||
void call() override {
|
||||
bool call() override {
|
||||
m_functor();
|
||||
return false;
|
||||
}
|
||||
|
||||
}; // struct impl_type
|
||||
|
||||
public:
|
||||
|
||||
// Constructor must not be "explicit" for wrapper
|
||||
// to work seemlessly.
|
||||
template <typename F>
|
||||
function_wrapper(F&& f) :
|
||||
impl(new impl_type<F>(std::move(f))) {
|
||||
template <typename TFunction>
|
||||
function_wrapper(TFunction&& f) :
|
||||
impl(new impl_type<TFunction>(std::forward<TFunction>(f))) {
|
||||
}
|
||||
|
||||
void operator()() {
|
||||
impl->call();
|
||||
// The integer parameter is only used to signal that we want
|
||||
// the special function wrapper that makes the worker thread
|
||||
// shut down.
|
||||
function_wrapper(int) :
|
||||
impl(new impl_base()) {
|
||||
}
|
||||
|
||||
bool operator()() {
|
||||
return impl->call();
|
||||
}
|
||||
|
||||
function_wrapper() = default;
|
||||
|
||||
+42
-15
@@ -54,6 +54,32 @@ namespace osmium {
|
||||
*/
|
||||
namespace thread {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Maximum number of allowed pool threads (just to keep the user
|
||||
// from setting something silly).
|
||||
constexpr const int max_pool_threads = 256;
|
||||
|
||||
inline int get_pool_size(int num_threads, int user_setting, unsigned hardware_concurrency) {
|
||||
if (num_threads == 0) {
|
||||
num_threads = user_setting ? user_setting : -2;
|
||||
}
|
||||
|
||||
if (num_threads < 0) {
|
||||
num_threads += hardware_concurrency;
|
||||
}
|
||||
|
||||
if (num_threads < 1) {
|
||||
num_threads = 1;
|
||||
} else if (num_threads > max_pool_threads) {
|
||||
num_threads = max_pool_threads;
|
||||
}
|
||||
|
||||
return num_threads;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Thread pool.
|
||||
*/
|
||||
@@ -83,7 +109,6 @@ namespace osmium {
|
||||
|
||||
}; // class thread_joiner
|
||||
|
||||
std::atomic<bool> m_done;
|
||||
osmium::thread::Queue<function_wrapper> m_work_queue;
|
||||
std::vector<std::thread> m_threads;
|
||||
thread_joiner m_joiner;
|
||||
@@ -91,11 +116,15 @@ namespace osmium {
|
||||
|
||||
void worker_thread() {
|
||||
osmium::thread::set_thread_name("_osmium_worker");
|
||||
while (!m_done) {
|
||||
while (true) {
|
||||
function_wrapper task;
|
||||
m_work_queue.wait_and_pop_with_timeout(task);
|
||||
if (task) {
|
||||
task();
|
||||
if (task()) {
|
||||
// The called tasks returns true only when the
|
||||
// worker thread should shut down.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,26 +142,17 @@ namespace osmium {
|
||||
* In all cases the minimum number of threads in the pool is 1.
|
||||
*/
|
||||
explicit Pool(int num_threads, size_t max_queue_size) :
|
||||
m_done(false),
|
||||
m_work_queue(max_queue_size, "work"),
|
||||
m_threads(),
|
||||
m_joiner(m_threads),
|
||||
m_num_threads(num_threads) {
|
||||
|
||||
if (m_num_threads == 0) {
|
||||
m_num_threads = osmium::config::get_pool_threads();
|
||||
}
|
||||
|
||||
if (m_num_threads <= 0) {
|
||||
m_num_threads = std::max(1, static_cast<int>(std::thread::hardware_concurrency()) + m_num_threads);
|
||||
}
|
||||
m_num_threads(detail::get_pool_size(num_threads, osmium::config::get_pool_threads(), std::thread::hardware_concurrency())) {
|
||||
|
||||
try {
|
||||
for (int i = 0; i < m_num_threads; ++i) {
|
||||
m_threads.push_back(std::thread(&Pool::worker_thread, this));
|
||||
}
|
||||
} catch (...) {
|
||||
m_done = true;
|
||||
shutdown_all_workers();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -147,8 +167,15 @@ namespace osmium {
|
||||
return pool;
|
||||
}
|
||||
|
||||
void shutdown_all_workers() {
|
||||
for (int i = 0; i < m_num_threads; ++i) {
|
||||
// The special function wrapper makes a worker shut down.
|
||||
m_work_queue.push(function_wrapper{0});
|
||||
}
|
||||
}
|
||||
|
||||
~Pool() {
|
||||
m_done = true;
|
||||
shutdown_all_workers();
|
||||
m_work_queue.shutdown();
|
||||
}
|
||||
|
||||
|
||||
+9
-2
@@ -75,6 +75,9 @@ namespace osmium {
|
||||
/// The largest size the queue has been so far.
|
||||
size_t m_largest_size;
|
||||
|
||||
/// The number of times push() was called on the queue.
|
||||
std::atomic<int> m_push_counter;
|
||||
|
||||
/// The number of times the queue was full and a thread pushing
|
||||
/// to the queue was blocked.
|
||||
std::atomic<int> m_full_counter;
|
||||
@@ -89,7 +92,7 @@ namespace osmium {
|
||||
* 0 for an unlimited size.
|
||||
* @param name Optional name for this queue. (Used for debugging.)
|
||||
*/
|
||||
Queue(size_t max_size = 0, const std::string& name = "") :
|
||||
explicit Queue(size_t max_size = 0, const std::string& name = "") :
|
||||
m_max_size(max_size),
|
||||
m_name(name),
|
||||
m_mutex(),
|
||||
@@ -99,6 +102,7 @@ namespace osmium {
|
||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||
,
|
||||
m_largest_size(0),
|
||||
m_push_counter(0),
|
||||
m_full_counter(0)
|
||||
#endif
|
||||
{
|
||||
@@ -107,7 +111,7 @@ namespace osmium {
|
||||
~Queue() {
|
||||
shutdown();
|
||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||
std::cerr << "queue '" << m_name << "' with max_size=" << m_max_size << " had largest size " << m_largest_size << " and was full " << m_full_counter << " times\n";
|
||||
std::cerr << "queue '" << m_name << "' with max_size=" << m_max_size << " had largest size " << m_largest_size << " and was full " << m_full_counter << " times in " << m_push_counter << " push() calls\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -116,6 +120,9 @@ namespace osmium {
|
||||
* call will block if the queue is full.
|
||||
*/
|
||||
void push(T value) {
|
||||
#ifdef OSMIUM_DEBUG_QUEUE_SIZE
|
||||
++m_push_counter;
|
||||
#endif
|
||||
if (m_max_size) {
|
||||
while (size() >= m_max_size) {
|
||||
std::this_thread::sleep_for(full_queue_sleep_duration);
|
||||
|
||||
+33
-4
@@ -49,7 +49,7 @@ namespace osmium {
|
||||
* the exception stored in the future if there was one. Otherwise it
|
||||
* will just return.
|
||||
*/
|
||||
template <class T>
|
||||
template <typename T>
|
||||
inline void check_for_exception(std::future<T>& future) {
|
||||
if (future.valid() && future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||
future.get();
|
||||
@@ -60,7 +60,7 @@ namespace osmium {
|
||||
* Wait until the given future becomes ready. Will block if the future
|
||||
* is not ready. Can be called more than once unlike future.get().
|
||||
*/
|
||||
template <class T>
|
||||
template <typename T>
|
||||
inline void wait_until_done(std::future<T>& future) {
|
||||
if (future.valid()) {
|
||||
future.get();
|
||||
@@ -71,15 +71,44 @@ namespace osmium {
|
||||
* Set name of current thread for debugging. This only works on Linux.
|
||||
*/
|
||||
#ifdef __linux__
|
||||
inline void set_thread_name(const char* name) {
|
||||
inline void set_thread_name(const char* name) noexcept {
|
||||
prctl(PR_SET_NAME, name, 0, 0, 0);
|
||||
}
|
||||
#else
|
||||
inline void set_thread_name(const char*) {
|
||||
inline void set_thread_name(const char*) noexcept {
|
||||
// intentionally left blank
|
||||
}
|
||||
#endif
|
||||
|
||||
class thread_handler {
|
||||
|
||||
std::thread m_thread;
|
||||
|
||||
public:
|
||||
|
||||
thread_handler() :
|
||||
m_thread() {
|
||||
}
|
||||
|
||||
template <typename TFunction, typename... TArgs>
|
||||
explicit thread_handler(TFunction&& f, TArgs&&... args) :
|
||||
m_thread(std::forward<TFunction>(f), std::forward<TArgs>(args)...) {
|
||||
}
|
||||
|
||||
thread_handler(const thread_handler&) = delete;
|
||||
thread_handler& operator=(const thread_handler&) = delete;
|
||||
|
||||
thread_handler(thread_handler&&) = default;
|
||||
thread_handler& operator=(thread_handler&&) = default;
|
||||
|
||||
~thread_handler() {
|
||||
if (m_thread.joinable()) {
|
||||
m_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
}; // class thread_handler
|
||||
|
||||
} // namespace thread
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
Reference in New Issue
Block a user