I have a С class that has a databases_list_ vector defined.
This vector contains database objects.
I need to make two functions that will run on separate threads.
And each function will use the databases_list_
vector.
That is, this vector is a shared resource for my functions.
In this case, I don't know the correct approach to secure the share so that every thread can use it.
// This is class Worker
class Worker {
private:
std::thread check_oo_thread_{}; // thread #1
std::thread check_db_thread_{}; // thread #2
void check_oo(); // func #1
void check_db(); // func #2
std::vector<std::unique_ptr<database>> databases_list_; // This is a shared resource
bool is_work_{ false };
}
// Here I am running two threads
void Worker::start() {
is_work_ = true;
check_oo_thread_ = std::thread(&Worker::check_oo, this);
check_db_thread_ = std::thread(&Worker::check_db, this);
}
And here are two functions that use the databases_list_ vector in different threads. The difference is that these functions get different data from the database - it depends on the command_type parameter
// In this function, each database object is called in turn
void Worker::check_oo() {
while (is_work_) {
for (auto& db : databases_list_) {
auto db_cfg = db->get_cfg();
data_handler_.set_database(db_cfg.db_server);
auto db_respond = db->send_command(receive_cmd, command_type::get_data);
}
std::this_thread::sleep_for(std::chrono::seconds(processing_period_1));
}
}
// In this function, each database object is called in turn
void Worker::check_db() {
while (is_work_) {
for (auto& db : databases_list_) {
auto db_cfg = db->get_cfg();
data_handler_.set_database(db_cfg.db_server);
auto db_respond = db->send_command(receive_cmd, command_type::get_stat);
}
std::this_thread::sleep_for(std::chrono::seconds(processing_period_2));
}
}
This is a tricky case for me and I can't figure out how to get two threads to work on the shared resource databases_list_.
CodePudding user response:
You can lock a std::mutex
every time you want to access the shared resource. You also access is_work_
from multiple threads and I therefore suggest making that std::atomic<bool> is_work_
instead.
#include <atomic>
#include <mutex>
class Worker {
private:
std::thread check_oo_thread_{}; // thread #1
std::thread check_db_thread_{}; // thread #2
mutable std::mutex m_mtx; // use this to sync actions on your resource
std::atomic<bool> is_work_{}; // now atomic
void check_oo() {
while(is_work_) {
{
std::lock_guard<std::mutex> lock{m_mtx}; // locks the mutex
// use databases_list_ here
} // mutex is unlocked here
std::this_thread::sleep_for(...);
}
}
void check_db() {
while(is_work_) {
{
std::lock_guard<std::mutex> lock{m_mtx};
// use databases_list_ here
}
std::this_thread::sleep_for(...);
}
}
std::vector<std::unique_ptr<database>> databases_list_;
};