diff --git a/MTQueue.h b/MTQueue.h index 38d2eee..b624206 100644 --- a/MTQueue.h +++ b/MTQueue.h @@ -43,29 +43,29 @@ class MTQueue { } }; -int main() { - MTQueue foods; - - std::thread t1([&] { - for (int i = 0; i < 2; i++) { - auto food = foods.pop(); - std::cout << "t1 got food:" << food << std::endl; - } - }); - - std::thread t2([&] { - for (int i = 0; i < 2; i++) { - auto food = foods.pop(); - std::cout << "t2 got food:" << food << std::endl; - } - }); - - foods.push(42); - foods.push(233); - foods.push_many({666, 4399}); - - t1.join(); - t2.join(); - - return 0; -} +//int main() { +// MTQueue foods; +// +// std::thread t1([&] { +// for (int i = 0; i < 2; i++) { +// auto food = foods.pop(); +// std::cout << "t1 got food:" << food << std::endl; +// } +// }); +// +// std::thread t2([&] { +// for (int i = 0; i < 2; i++) { +// auto food = foods.pop(); +// std::cout << "t2 got food:" << food << std::endl; +// } +// }); +// +// foods.push(42); +// foods.push(233); +// foods.push_many({666, 4399}); +// +// t1.join(); +// t2.join(); +// +// return 0; +//} diff --git a/main.cpp b/main.cpp index f4ecab8..7b5ed3c 100644 --- a/main.cpp +++ b/main.cpp @@ -6,7 +6,13 @@ #include #include #include +#include +#include +//reference:https://github.com/parallel101/hw05/pull/1/files + +std::shared_mutex mtx_; // for username lock +std::shared_mutex mtx2_;// for has_login lock struct User { std::string password; @@ -15,12 +21,14 @@ struct User { }; std::map users; -std::map has_login; // 换成 std::chrono::seconds 之类的 +//std::map has_login; // 换成 std::chrono::seconds 之类的 +std::map has_login; // 作业要求1:把这些函数变成多线程安全的 // 提示:能正确利用 shared_mutex 加分,用 lock_guard 系列加分 std::string do_register(std::string username, std::string password, std::string school, std::string phone) { User user = {password, school, phone}; + std::unique_lock grd{mtx_}; if (users.emplace(username, user).second) return "注册成功"; else @@ -29,13 +37,22 @@ std::string do_register(std::string username, std::string password, std::string std::string do_login(std::string username, std::string password) { // 作业要求2:把这个登录计时器改成基于 chrono 的 - long now = time(NULL); // C 语言当前时间 - if (has_login.find(username) != has_login.end()) { - int sec = now - has_login.at(username); // C 语言算时间差 - return std::to_string(sec) + "秒内登录过"; +// long now = time(NULL); // C 语言当前时间 + auto now = std::chrono::steady_clock::now(); + { + std:: unique_lock ugrd{mtx2_}; + if (has_login.find(username) != has_login.end()) { +// int sec = now - has_login.at(username); // C 语言算时间差 +// return std::to_string(sec) + "秒内登录过"; + auto dt = now - has_login.at(username); + if (dt <= std::chrono::seconds(10)) { + int64_t sec = std::chrono::duration_cast(dt).count(); + return std::to_string(sec) + "秒内登录过"; + } + } + has_login[username] = now; } - has_login[username] = now; - + std::shared_lock grd{mtx_}; if (users.find(username) == users.end()) return "用户名错误"; if (users.at(username).password != password) @@ -44,6 +61,10 @@ std::string do_login(std::string username, std::string password) { } std::string do_queryuser(std::string username) { + std::shared_lock grd{mtx_}; + if( users.find(username) == users.end()){ + return "没有该用户"; + } auto &user = users.at(username); std::stringstream ss; ss << "用户名: " << username << std::endl; @@ -54,15 +75,58 @@ std::string do_queryuser(std::string username) { struct ThreadPool { + std::vector workers; + std::vector> tasks; + std::mutex mtx; + std::condition_variable condition; + bool stop; + + ThreadPool(int num_workers = std::thread::hardware_concurrency()):stop(false){ + for(int i = 0;i < num_workers;++i){ + workers.emplace_back([this]{ + while(true){ + std::function t; + { + std::unique_lock lck(mtx); + condition.wait(lck,[this]{return stop || !tasks.empty();}); + if(stop && tasks.empty()) return ; + t = std::move(tasks.back()); + tasks.pop_back(); + } + t(); + } + }); + std::cout<<"Thread: "< start) { // 作业要求3:如何让这个线程保持在后台执行不要退出? // 提示:改成 async 和 future 且用法正确也可以加分 - std::thread thr(start); +// std::thread thr(start); + { + std::unique_lock lck(mtx); + tasks.push_back(start); + } + condition.notify_one(); + return ; } }; -ThreadPool tpool; - +//ThreadPool tpool; +ThreadPool tpool(12); namespace test { // 测试用例?出水用力! std::string username[] = {"张心欣", "王鑫磊", "彭于斌", "胡原名"}; @@ -72,7 +136,9 @@ std::string phone[] = {"110", "119", "120", "12315"}; } int main() { - for (int i = 0; i < 262144; i++) { + for (int i = 0; i < 20000; i++) { + // 从test中不断随机采样 + std::cout<<"for i #### = "<< i << std::endl; tpool.create([&] { std::cout << do_register(test::username[rand() % 4], test::password[rand() % 4], test::school[rand() % 4], test::phone[rand() % 4]) << std::endl; }); @@ -85,5 +151,6 @@ int main() { } // 作业要求4:等待 tpool 中所有线程都结束后再退出 + std::cout<<"all printed !" <