diff --git a/main.cpp b/main.cpp index f4ecab8..5691ba6 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,11 @@ #include #include #include +#include +#include +#include +#include +#include "MTQueue.h" struct User { @@ -15,11 +20,14 @@ struct User { }; std::map users; -std::map has_login; // 换成 std::chrono::seconds 之类的 +std::shared_mutex users_mutex; +std::map has_login; // 换成 std::chrono::seconds 之类的 +std::shared_mutex login_mutex; // 作业要求1:把这些函数变成多线程安全的 // 提示:能正确利用 shared_mutex 加分,用 lock_guard 系列加分 std::string do_register(std::string username, std::string password, std::string school, std::string phone) { + std::unique_lock grd(users_mutex); User user = {password, school, phone}; if (users.emplace(username, user).second) return "注册成功"; @@ -29,13 +37,16 @@ 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 语言当前时间 + auto now = std::chrono::steady_clock::now(); // C 语言当前时间 + std::unique_lock grd1(login_mutex); if (has_login.find(username) != has_login.end()) { - int sec = now - has_login.at(username); // C 语言算时间差 + int64_t sec = std::chrono::duration_cast(now - has_login.at(username)).count(); // C 语言算时间差 return std::to_string(sec) + "秒内登录过"; } has_login[username] = now; + grd1.unlock(); + std::shared_lock grd2(users_mutex); if (users.find(username) == users.end()) return "用户名错误"; if (users.at(username).password != password) @@ -44,7 +55,11 @@ std::string do_login(std::string username, std::string password) { } std::string do_queryuser(std::string username) { - auto &user = users.at(username); + std::shared_lock grd(users_mutex); + if (users.find(username) == users.end()) + return ""; + auto user = users.at(username); + grd.unlock(); std::stringstream ss; ss << "用户名: " << username << std::endl; ss << "学校:" << user.school << std::endl; @@ -52,16 +67,21 @@ std::string do_queryuser(std::string username) { return ss.str(); } - struct ThreadPool { +private: + std::vector m_pool; +public: void create(std::function start) { - // 作业要求3:如何让这个线程保持在后台执行不要退出? - // 提示:改成 async 和 future 且用法正确也可以加分 std::thread thr(start); + m_pool.push_back(std::move(thr)); + } + ~ThreadPool() { + for (auto &thr: m_pool) + thr.join(); } }; -ThreadPool tpool; +ThreadPool tpool{}; namespace test { // 测试用例?出水用力! @@ -74,16 +94,20 @@ std::string phone[] = {"110", "119", "120", "12315"}; int main() { for (int i = 0; i < 262144; i++) { tpool.create([&] { - std::cout << do_register(test::username[rand() % 4], test::password[rand() % 4], test::school[rand() % 4], test::phone[rand() % 4]) << std::endl; + do_register(test::username[rand() % 4], test::password[rand() % 4], test::school[rand() % 4], test::phone[rand() % 4]); + // std::cout << do_register(test::username[rand() % 4], test::password[rand() % 4], test::school[rand() % 4], test::phone[rand() % 4]) << std::endl; }); tpool.create([&] { - std::cout << do_login(test::username[rand() % 4], test::password[rand() % 4]) << std::endl; + do_login(test::username[rand() % 4], test::password[rand() % 4]); + // std::cout << do_login(test::username[rand() % 4], test::password[rand() % 4]) << std::endl; }); tpool.create([&] { - std::cout << do_queryuser(test::username[rand() % 4]) << std::endl; + do_queryuser(test::username[rand() % 4]); + // std::cout << do_queryuser(test::username[rand() % 4]) << std::endl; }); } // 作业要求4:等待 tpool 中所有线程都结束后再退出 + std::cout << "ALL DONE" << std::endl; return 0; }