Commit bfa303d5d242fc5ec75cec22b0e789277eb2a2ea
1 parent
87ff8a3e
Added block_until_stopped method
Used to block the main thread until the event loop is stopped by calling the .stop() method. Implemented using a condition_variable, and very useful for clients.
Showing
3 changed files
with
18 additions
and
8 deletions
examples/lpush_benchmark.cpp
| ... | ... | @@ -3,7 +3,6 @@ |
| 3 | 3 | */ |
| 4 | 4 | |
| 5 | 5 | #include <iostream> |
| 6 | -#include <mutex> | |
| 7 | 6 | #include "../src/redisx.hpp" |
| 8 | 7 | |
| 9 | 8 | using namespace std; |
| ... | ... | @@ -18,6 +17,7 @@ int main(int argc, char* argv[]) { |
| 18 | 17 | redisx::Redis rdx = {"localhost", 6379}; |
| 19 | 18 | rdx.run(); |
| 20 | 19 | |
| 20 | + // TODO wait for this somehow | |
| 21 | 21 | rdx.command("DEL test"); |
| 22 | 22 | |
| 23 | 23 | unsigned long t0 = time_ms(); |
| ... | ... | @@ -25,11 +25,9 @@ int main(int argc, char* argv[]) { |
| 25 | 25 | |
| 26 | 26 | int len = 1000000; |
| 27 | 27 | int count = 0; |
| 28 | - mutex task_lock; | |
| 29 | 28 | |
| 30 | - task_lock.lock(); | |
| 31 | 29 | for(int i = 1; i <= len; i++) { |
| 32 | - rdx.command<int>("lpush test 1", [&t0, &t1, &count, len, &task_lock](const string& cmd, int reply) { | |
| 30 | + rdx.command<int>("lpush test 1", [&t0, &t1, &count, len, &rdx](const string& cmd, int reply) { | |
| 33 | 31 | |
| 34 | 32 | count++; |
| 35 | 33 | if(count == len) { |
| ... | ... | @@ -40,14 +38,12 @@ int main(int argc, char* argv[]) { |
| 40 | 38 | cout << "Time to receive all: " << t2 - t1 << "ms" << endl; |
| 41 | 39 | cout << "Total time: " << t2 - t0 << "ms" << endl; |
| 42 | 40 | |
| 43 | - task_lock.unlock(); | |
| 41 | + rdx.stop(); | |
| 44 | 42 | } |
| 45 | 43 | }); |
| 46 | 44 | } |
| 47 | 45 | t1 = time_ms(); |
| 48 | 46 | |
| 49 | - task_lock.lock(); | |
| 50 | - rdx.stop(); | |
| 51 | - | |
| 47 | + rdx.block_until_stopped(); | |
| 52 | 48 | return 0; |
| 53 | 49 | }; | ... | ... |
src/redisx.cpp
| ... | ... | @@ -73,6 +73,10 @@ void Redis::run_blocking() { |
| 73 | 73 | |
| 74 | 74 | // Handle exit events |
| 75 | 75 | ev_run(EV_DEFAULT_ EVRUN_NOWAIT); |
| 76 | + | |
| 77 | + // Let go for block_until_stopped method | |
| 78 | + unique_lock<mutex> ul(exit_waiter_lock); | |
| 79 | + exit_waiter.notify_one(); | |
| 76 | 80 | } |
| 77 | 81 | |
| 78 | 82 | void Redis::run() { |
| ... | ... | @@ -85,6 +89,11 @@ void Redis::stop() { |
| 85 | 89 | to_exit = true; |
| 86 | 90 | } |
| 87 | 91 | |
| 92 | +void Redis::block_until_stopped() { | |
| 93 | + unique_lock<mutex> ul(exit_waiter_lock); | |
| 94 | + exit_waiter.wait(ul, [this]() { return to_exit.load(); }); | |
| 95 | +} | |
| 96 | + | |
| 88 | 97 | template<class ReplyT> |
| 89 | 98 | bool Redis::submit_to_server(const CommandAsync<ReplyT>* cmd_obj) { |
| 90 | 99 | if (redisAsyncCommand(c, command_callback<ReplyT>, (void*)cmd_obj, cmd_obj->cmd.c_str()) != REDIS_OK) { | ... | ... |
src/redisx.hpp
| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | |
| 10 | 10 | #include <thread> |
| 11 | 11 | #include <mutex> |
| 12 | +#include <condition_variable> | |
| 12 | 13 | #include <atomic> |
| 13 | 14 | |
| 14 | 15 | #include <string> |
| ... | ... | @@ -17,6 +18,7 @@ |
| 17 | 18 | |
| 18 | 19 | #include <hiredis/hiredis.h> |
| 19 | 20 | #include <hiredis/async.h> |
| 21 | +#include <condition_variable> | |
| 20 | 22 | |
| 21 | 23 | namespace redisx { |
| 22 | 24 | |
| ... | ... | @@ -47,6 +49,7 @@ public: |
| 47 | 49 | void run(); |
| 48 | 50 | void run_blocking(); |
| 49 | 51 | void stop(); |
| 52 | + void block_until_stopped(); | |
| 50 | 53 | |
| 51 | 54 | template<class ReplyT> |
| 52 | 55 | void command( |
| ... | ... | @@ -84,6 +87,8 @@ private: |
| 84 | 87 | redisAsyncContext *c; |
| 85 | 88 | |
| 86 | 89 | std::atomic_bool to_exit; |
| 90 | + std::mutex exit_waiter_lock; | |
| 91 | + std::condition_variable exit_waiter; | |
| 87 | 92 | |
| 88 | 93 | std::thread event_loop_thread; |
| 89 | 94 | ... | ... |