multithreading - Threads handling in C++ 11 -
i have base class, manages threaded functions , derived, can set it's functions run concurrently of base class. during test in emulating fast starts/stops of function, programs crashes. seems, problem in mutexes can wrong. problem?
class threadedbase { public: threadedbase(){} virtual ~threadedbase() { (int = 0; < m_threadedtasks.size(); ++i) { *m_threadedtasks[i]->run = false; m_threadedtasks[i]->thread->join(); } while (m_threadedtasks.size()) { m_threadedtasks.erase(m_threadedtasks.begin()); } } void addtask(std::function<void()> f) { static int = 0; m_threadedtasks.insert({ i++, new threadedtask(f)}); } void startn(int n) { std::lock_guard<std::mutex> lock(m_threadedtasks[n]->mtx); std::cout << "startn\n"; if (*m_threadedtasks[n]->run == true) return; *m_threadedtasks[n]->run = true; m_threadedtasks[n]->thread = new std::thread((std::mem_fn(&threadedbase::run)), this, n); } void stopn(int n) { std::lock_guard<std::mutex> lock(m_threadedtasks[n]->mtx); std::cout << "stopn\n"; *m_threadedtasks[n]->run = false; } private: struct threadedtask { threadedtask(std::function<void()> f) : function(f), thread(nullptr), run(new bool(false)) {} ~threadedtask() { thread->join(); delete thread; delete run; } std::function<void()> function; std::thread *thread; mutable std::mutex mtx; bool *run; }; std::unordered_map<int, threadedtask*> m_threadedtasks; void run(int n) { while (*m_threadedtasks[n]->run) { std::lock_guard<std::mutex> lock(m_threadedtasks[n]->mtx); m_threadedtasks[n]->function(); std::cout << "yet loop\n"; } // todo: erase if needed std::lock_guard<std::mutex> lock(m_threadedtasks[n]->mtx); *m_threadedtasks[n]->run = false; delete m_threadedtasks[n]->thread; m_threadedtasks[n]->thread = nullptr; } }; class test : public threadedbase { public: test() : threadedbase() { addtask(std::bind(std::mem_fn(&test::threadedblock1), this)); addtask(std::bind(std::mem_fn(&test::threadedblock2), this)); }; void threadedblock1() { std::this_thread::sleep_for(std::chrono::milliseconds(200)); std::cout << "task1 finished "; } void threadedblock2() { std::this_thread::sleep_for(std::chrono::milliseconds(200)); std::cout << "task2 finished "; } ~test() { std::cout << "deleting\n"; } void startn(int n) { threadedbase::startn(n); } void stopn(int n) { threadedbase::stopn(n); } }; int main() { test *t = new test(); srand(time(null)); while (true) { (0 + rand() % 2 == 0) ? t->startn(0) : t->stopn(0); } std::this_thread::sleep_for(std::chrono::seconds(100)); return 0; }
thank's joachim pileborg i've made code work. following:
class threadedbase { public: threadedbase(){} virtual ~threadedbase() { (int = 0; < m_threadedtasks.size(); ++i) { m_threadedtasks[i]->run = false; m_threadedtasks[i]->thread.join(); } while (m_threadedtasks.size()) { m_threadedtasks.erase(m_threadedtasks.begin()); } } void addtask(std::function<void()> f) { static int = 0; m_threadedtasks.insert({ i++, new threadedtask(f) }); } void startn(int n) { std::lock_guard<std::mutex> lock(m_threadedtasks[n]->mtx); if (m_threadedtasks[n]->run == true) return; m_threadedtasks[n]->run = true; m_threadedtasks[n]->thread = std::thread(&threadedbase::run, this, n); } void stopn(int n) { m_threadedtasks[n]->run = false; if (m_threadedtasks[n]->thread.joinable()) m_threadedtasks[n]->thread.join(); } private: struct threadedtask { threadedtask(std::function<void()> f) : function(f), thread(), mtx(), run(false) {} ~threadedtask() { thread.join(); } std::function<void()> function; std::thread thread; mutable std::mutex mtx; bool run; }; std::unordered_map<int, threadedtask*> m_threadedtasks; void run(int n) { while (m_threadedtasks[n]->run) { std::lock_guard<std::mutex> lock(m_threadedtasks[n]->mtx); m_threadedtasks[n]->function(); std::cout << "yet loop\n"; } // todo: erase if needed m_threadedtasks[n]->run = false; } }; class test : public threadedbase { public: test() : threadedbase() { addtask(std::bind(&test::threadedblock1, this)); addtask(std::bind(&test::threadedblock2, this)); }; void threadedblock1() { std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::cout << "task1 finished "; } void threadedblock2() { std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::cout << "task2 finished "; } ~test() { std::cout << "deleting\n"; } void startn(int n) { threadedbase::startn(n); } void stopn(int n) { threadedbase::stopn(n); } }; int main() { test *t = new test(); srand(time(null)); while (true) { (0 + rand() % 2 == 0) ? t->startn(0) : t->stopn(0); } std::this_thread::sleep_for(std::chrono::seconds(100)); return 0; }
Comments
Post a Comment