1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-11-10 20:10:05 +00:00

Merge branch 'better-concurrency' into next

This commit is contained in:
Carles Fernandez 2024-08-08 10:39:18 +02:00
commit 9ffb7e2dc8
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
2 changed files with 49 additions and 52 deletions

View File

@ -36,52 +36,48 @@ template <typename Data>
*/ */
class Concurrent_Map class Concurrent_Map
{ {
typedef typename std::map<int, Data>::iterator Data_iterator; // iterator is scope dependent
public: public:
void write(int key, Data const& data) void write(int key, Data const& data)
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::lock_guard<std::mutex> lock(the_mutex);
Data_iterator data_iter; auto data_iter = the_map.find(key);
data_iter = the_map.find(key);
if (data_iter != the_map.end()) if (data_iter != the_map.end())
{ {
data_iter->second = data; // update data_iter->second = data; // update
} }
else else
{ {
the_map.insert(std::pair<int, Data>(key, data)); // insert SILENTLY fails if the item already exists in the map! the_map.insert(std::pair<int, Data>(key, data)); // insert does not overwrite if the item already exists in the map!
} }
lock.unlock();
} }
std::map<int, Data> get_map_copy() std::map<int, Data> get_map_copy() const&
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::lock_guard<std::mutex> lock(the_mutex);
std::map<int, Data> map_aux = the_map; return the_map; // This implicitly creates a copy
lock.unlock();
return map_aux;
} }
size_t size() std::map<int, Data> get_map_copy() &&
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::lock_guard<std::mutex> lock(the_mutex);
size_t size_ = the_map.size(); return std::move(the_map);
lock.unlock();
return size_;
} }
bool read(int key, Data& p_data) size_t size() const
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::lock_guard<std::mutex> lock(the_mutex);
Data_iterator data_iter; return the_map.size();
data_iter = the_map.find(key); }
bool read(int key, Data& p_data) const
{
std::lock_guard<std::mutex> lock(the_mutex);
auto data_iter = the_map.find(key);
if (data_iter != the_map.end()) if (data_iter != the_map.end())
{ {
p_data = data_iter->second; p_data = data_iter->second;
lock.unlock();
return true; return true;
} }
lock.unlock();
return false; return false;
} }

View File

@ -19,9 +19,10 @@
#include <chrono> #include <chrono>
#include <condition_variable> #include <condition_variable>
#include <cstddef>
#include <mutex> #include <mutex>
#include <queue> #include <queue>
#include <thread> #include <utility>
/** \addtogroup Core /** \addtogroup Core
* \{ */ * \{ */
@ -33,48 +34,53 @@ template <typename Data>
/*! /*!
* \brief This class implements a thread-safe std::queue * \brief This class implements a thread-safe std::queue
*
* Thread-safe object queue which uses the library
* boost_thread to perform MUTEX based on the code available at
* https://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
*/ */
class Concurrent_Queue class Concurrent_Queue
{ {
public: public:
void push(Data const& data) void push(const Data& data)
{ {
std::unique_lock<std::mutex> lock(the_mutex); {
the_queue.push(data); std::lock_guard<std::mutex> lock(the_mutex);
lock.unlock(); the_queue.push(data);
}
the_condition_variable.notify_one(); the_condition_variable.notify_one();
} }
bool empty() const void push(Data&& data)
{ {
std::unique_lock<std::mutex> lock(the_mutex); {
return the_queue.empty(); std::lock_guard<std::mutex> lock(the_mutex);
the_queue.push(std::move(data));
}
the_condition_variable.notify_one();
} }
size_t size() const bool empty() const noexcept
{ {
std::unique_lock<std::mutex> lock(the_mutex); return size() == 0;
}
size_t size() const noexcept
{
std::lock_guard<std::mutex> lock(the_mutex);
return the_queue.size(); return the_queue.size();
} }
void clear() void clear()
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::lock_guard<std::mutex> lock(the_mutex);
the_queue = std::queue<Data>(); std::queue<Data>().swap(the_queue);
} }
bool try_pop(Data& popped_value) bool try_pop(Data& popped_value)
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::lock_guard<std::mutex> lock(the_mutex);
if (the_queue.empty()) if (the_queue.empty())
{ {
return false; return false;
} }
popped_value = the_queue.front(); popped_value = std::move(the_queue.front());
the_queue.pop(); the_queue.pop();
return true; return true;
} }
@ -82,26 +88,21 @@ public:
void wait_and_pop(Data& popped_value) void wait_and_pop(Data& popped_value)
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::unique_lock<std::mutex> lock(the_mutex);
while (the_queue.empty()) the_condition_variable.wait(lock, [this] { return !the_queue.empty(); });
{ popped_value = std::move(the_queue.front());
the_condition_variable.wait(lock);
}
popped_value = the_queue.front();
the_queue.pop(); the_queue.pop();
} }
bool timed_wait_and_pop(Data& popped_value, int wait_ms) bool timed_wait_and_pop(Data& popped_value, int wait_ms)
{ {
std::unique_lock<std::mutex> lock(the_mutex); std::unique_lock<std::mutex> lock(the_mutex);
if (the_queue.empty()) if (!the_condition_variable.wait_for(lock,
std::chrono::milliseconds(wait_ms),
[this] { return !the_queue.empty(); }))
{ {
the_condition_variable.wait_for(lock, std::chrono::milliseconds(wait_ms)); return false;
if (the_queue.empty())
{
return false;
}
} }
popped_value = the_queue.front(); popped_value = std::move(the_queue.front());
the_queue.pop(); the_queue.pop();
return true; return true;
} }