在这个多核时代,服务端网络编程如何选择线程模型?libevent作者的观点:one loop(事件循环, 一般用IO复用作为事件分发器) per thread is usually a good model. 多线程服务端编程的问题就转换为如何设计一个高效且易用的event loop,然后每个线程run一个event loop就行了【即muduo库的思想】(当然线程间的同步、互斥少不了,还有其他的耗时事件需要起另外的线程来做)。
The Reactor design pattern is an event handling pattern for handling service requests delivered concurrentlyto a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatchers them synchronously to the associated request handlers.
root@tony-virtual-machine:/home/tony/package# ls build muduo-master muduo-master.zip root@tony-virtual-machine:/home/tony/package# cd build/ root@tony-virtual-machine:/home/tony/package/build# ls release-cpp11 release-install-cpp11 root@tony-virtual-machine:/home/tony/package/build# cd release-install-cpp11/ root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11# ls include lib
root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11# ls include lib root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11# cd include/ root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11/include# ls muduo root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11/include# mv muduo/ /usr/include/ root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11/include# cd .. root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11# ls include lib root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11# cd lib/ root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11/lib# ls libmuduo_base.a libmuduo_http.a libmuduo_inspect.a libmuduo_net.a root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11/lib# mv * /usr/local/lib/ root@tony-virtual-machine:/home/tony/package/build/release-install-cpp11/lib#
root@tony-virtual-machine:/home/tony/code# ./a.out 20190404 08:00:15.254790Z 42660 INFO pid = 42660 - main.cpp:61 20190404 08:00:59.438626Z 42660 INFO TcpServer::newConnection [EchoServer] - new connection [EchoServer-0.0.0.0:8888#1] from 127.0.0.1:33480 - TcpServer.cc:80 20190404 08:00:59.438707Z 42660 INFO EchoServer - 127.0.0.1:33480 -> 127.0.0.1:8888 is UP - main.cpp:42 20190404 08:00:59.438812Z 42660 INFO EchoServer-0.0.0.0:8888#1 echo 12 bytes, data received at 1554364859.438723 - main.cpp:53
Station #1: 100 Station #1: 99 ... Station #1: ... ... Station #1: 89 Station #1: 88 Station #1: 87 Station #2: 86 Station #2: 85 ... Station #2: ... ... Station #2: 67 Station #2: 66 Station #2: 65 Station #2: 64 Station #2: 63 Station #2: 62 Station #1: 61 Station #1: 60 ... Station #1: ... ... Station #1: 5 Station #1: 4 Station #1: 3 Station #1: 2 Station #1: 1 Station #2: 0
Station #1: 500 Station #1: 499 ... Station #1: ... ... Station #1: 394 Station #1: 393 ---------------------- Station #2: 392 Station #2: 391 ... Station #2: ... ... Station #2: 5 Station #2: 4 Station #2: 3 Station #2: 2 Station #2: 1
构造tha时的第三个参数是my_reference_wrapper<int>(x),是个右值!传入thread可变参模板函数,完美转发,右值叠加右值,依然是右值,调用_Start时优先匹配&&类型的参数,但是发现没有,而且只有一个匹配的选项是:(int n, int & x),是int&类型,于是乎,无奈之举,调用成员函数operator _Ty(),即为隐式转换为&Ty的左值引用类型。
Station #1: 100 Station #1: 99 ... Station #1: ... ... Station #1: 67 Station #1: 66 Station #2: 65 Station #2: 64 ... Station #2: ... ... Station #2: 8 Station #2: 7 Station #2: 6 Station #2: 5 Station #2: 4 Station #2: 3 Station #2: 2 Station #2: 1
shared_mutex(共享互斥量)
定义于<shared_mutex>,C++17给出的共享互斥量。
Shared mutexes are especially useful when shared data can be safely read by any number of threads simultaneously, but a thread may only write the same data when no other thread is reading or writing at the same time.
尽管并不是所有情况下都严格需要,但有效且简单的做法还是在使用条件变量发送notify信号时持有锁(指要发送notify的线程)。有的例子是必须加锁的情况,但也有一些情况可以不加锁,而这可能是你应该避免(避免再去分情况考虑)的。因此,为了简单,请在调用 signal(也就是notify) 时持有锁(hold the lock when calling signal)。
Got the Notify to Start! 0 Timeout: No Notify 1 Timeout: No Notify 2 Timeout: No Notify 3 Timeout: No Notify 4 Timeout: No Notify 5 Timeout: No Notify 6 Timeout: No Notify 7 Timeout: No Notify 8 Timeout: No Notify 9 Timeout: No Notify 10 Timeout: No Notify 11 Timeout: No Notify 12 Timeout: No Notify 13 Timeout: No Notify 14 Timeout: No Notify 15 Timeout: No Notify 16 Timeout: No Notify 17 Timeout: No Notify 18 Timeout: No Notify 19 Timeout: No Notify 20 Timeout: No Notify 21 Timeout: No Notify 22 Timeout: No Notify 23 Timeout: No Notify 24 Timeout: No Notify 25 Timeout: No Notify 26 Timeout: No Notify 27 Timeout: No Notify 28 Timeout: No Notify 29 Timeout: No Notify 30 Timeout: No Notify 31 Timeout: No Notify 32 Timeout: No Notify 33 Timeout: No Notify 34 Timeout: No Notify 35 Timeout: No Notify 36 Timeout: No Notify 37 Timeout: No Notify 38 Timeout: No Notify 39 Timeout: No Notify 40 Timeout: No Notify 41 Timeout: No Notify 42 Timeout: No Notify 43 Timeout: No Notify 44 Timeout: No Notify 45 Timeout: No Notify 46 Timeout: No Notify 47 Timeout: No Notify 48 Got the Notify to Out!
After Sleep 1s... Before Sleep 8s... Got the Notify to Start! 0 Timeout: No Notify 1 Timeout: No Notify 2 Timeout: No Notify 3 Timeout: No Notify 4 Timeout: No Notify 5 Got the Notify to Out!
After Sleep 1s... Before Sleep 8s... Got the Notify to Start! 0 Timeout: No Notify 1 Timeout: No Notify 2 Timeout: No Notify 3 Timeout: No Notify 4 Timeout: No Notify 5 Timeout: No Notify 6 Timeout: No Notify 7 Timeout: No Notify 8 Timeout: No Notify 9 Timeout: No Notify 10 Timeout: No Notify 11 Timeout: No Notify 12 Timeout: No Notify 13 Timeout: No Notify 14 Timeout: No Notify 15 Timeout: No Notify 16 Timeout: No Notify 17 Timeout: No Notify 18 Timeout: No Notify 19 Timeout: No Notify 20 Timeout: No Notify 21 Timeout: No Notify 22 Timeout: No Notify 23 Timeout: No Notify 24 Timeout: No Notify 25 Timeout: No Notify 26 Timeout: No Notify 27 Timeout: No Notify 28 Timeout: No Notify 29 Timeout: No Notify 30 Timeout: No Notify 31 Timeout: No Notify 32 Timeout: No Notify 33 Timeout: No Notify 34 Timeout: No Notify 35 Timeout: No Notify 36 Timeout: No Notify 37 Timeout: No Notify 38 Timeout: No Notify 39 Timeout: No Notify 40 Timeout: No Notify 41 Timeout: No Notify 42 Timeout: No Notify 43 Timeout: No Notify 44 Timeout: No Notify 45 Timeout: No Notify 46 Timeout: No Notify 47 Timeout: No Notify 48 Timeout: No Notify 49 Timeout: No Notify 50 Timeout: No Notify 51 Timeout: No Notify 52 Timeout: No Notify 53 Timeout: No Notify 54 Timeout: No Notify 55 Timeout: No Notify 56 Timeout: No Notify 57 Timeout: No Notify 58 Timeout: No Notify 59 Timeout: No Notify 60 Timeout: No Notify 61 Timeout: No Notify 62 Timeout: No Notify 63 Timeout: No Notify 64 Timeout: No Notify 65 Timeout: No Notify 66 Timeout: No Notify 67 Timeout: No Notify 68 Timeout: No Notify 69 Timeout: No Notify 70 Timeout: No Notify 71 Timeout: No Notify 72 Timeout: No Notify 73 Timeout: No Notify 74 Timeout: No Notify 75 Timeout: No Notify 76 Timeout: No Notify 77 Timeout: No Notify 78 Timeout: No Notify 79 Timeout: No Notify 80 Timeout: No Notify 81 Timeout: No Notify 82 Timeout: No Notify 83 Timeout: No Notify 84 Timeout: No Notify 85 Timeout: No Notify 86 Timeout: No Notify 87 Timeout: No Notify 88 Timeout: No Notify 89 Timeout: No Notify 90 Timeout: No Notify 91 Timeout: No Notify 92 Timeout: No Notify 93 Timeout: No Notify 94 Timeout: No Notify 95 Timeout: No Notify 96 Timeout: No Notify 97 Timeout: No Notify 98 Timeout: No Notify 99 Timeout: No Notify 100 Timeout: No Notify 101 Timeout: No Notify 102 Timeout: No Notify 103 Timeout: No Notify 104 Timeout: No Notify 105 Timeout: No Notify 106 Timeout: No Notify 107 Timeout: No Notify 108 Timeout: No Notify 109 Timeout: No Notify 110 Timeout: No Notify 111 Timeout: No Notify 112 Timeout: No Notify 113 Timeout: No Notify 114 Timeout: No Notify 115 Timeout: No Notify 116 Timeout: No Notify 117 Timeout: No Notify 118 Timeout: No Notify 119 Timeout: No Notify 120 Timeout: No Notify 121 Timeout: No Notify 122 Timeout: No Notify 123 Timeout: No Notify 124 Timeout: No Notify 125 Timeout: No Notify 126 Timeout: No Notify 127 Timeout: No Notify 128 Timeout: No Notify 129 After Sleep 8s... Got the Notify to Out!
intmain() { auto fut = std::async([](int v) -> int { for (auto i = v; i > 0; --i) { std::cout << i << std::endl; std::this_thread::sleep_for(200ms); } return3; }, 50); int v = fut.get(); std::wcout << L"main thread got a value: " << v << std::endl; }
intmain() { auto fut = std::async([](int v) -> int { for (auto i = v; i > 0; --i) { std::cout << i << std::endl; std::this_thread::sleep_for(200ms); } return3; }, 50); std::wcout << L"main thread begin to Sleep..." << std::endl; std::this_thread::sleep_for(5s); std::wcout << L"main thread Wake up" << std::endl; int v = fut.get(); std::wcout << L"main thread got a value: " << v << std::endl; }
intmain() { auto fut = std::async(std::launch::deferred, [](int v) -> int { for (auto i = v; i > 0; --i) { std::cout << i << std::endl; std::this_thread::sleep_for(200ms); } return3; }, 50); std::wcout << L"main thread begin to Sleep..." << std::endl; std::this_thread::sleep_for(5s); std::wcout << L"main thread Wake up" << std::endl; int v = fut.get(); std::wcout << L"main thread got a value: " << v << std::endl; }