Commit fb65a72153bca297b152595a415959dfe0f5e1f4

Authored by Hayk Martirosyan
1 parent c21560d9

Rename redisx->redox, refactor

Move as much as possible into the .cpp file, and clean things up.
CMakeLists.txt
1 cmake_minimum_required(VERSION 2.8.4) 1 cmake_minimum_required(VERSION 2.8.4)
2 -project(redisx) 2 +project(redox)
3 3
4 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -O3") 4 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -O3")
5 #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -g -fno-omit-frame-pointer") 5 #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -g -fno-omit-frame-pointer")
@@ -12,7 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -O3") @@ -12,7 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -O3")
12 set(SRC_DIR ${CMAKE_SOURCE_DIR}/src) 12 set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
13 13
14 set(SRC_CORE 14 set(SRC_CORE
15 - ${SRC_DIR}/redisx.cpp 15 + ${SRC_DIR}/redox.cpp
16 ) 16 )
17 17
18 set(SRC_ALL ${SRC_CORE}) 18 set(SRC_ALL ${SRC_CORE})
examples/simple_loop.cpp
@@ -3,10 +3,10 @@ @@ -3,10 +3,10 @@
3 */ 3 */
4 4
5 #include <iostream> 5 #include <iostream>
6 -#include "../src/redisx.hpp" 6 +#include "../src/redox.hpp"
7 7
8 using namespace std; 8 using namespace std;
9 -using namespace redisx; 9 +using namespace redox;
10 10
11 double time_s() { 11 double time_s() {
12 unsigned long ms = chrono::system_clock::now().time_since_epoch() / chrono::microseconds(1); 12 unsigned long ms = chrono::system_clock::now().time_since_epoch() / chrono::microseconds(1);
@@ -15,7 +15,7 @@ double time_s() { @@ -15,7 +15,7 @@ double time_s() {
15 15
16 int main(int argc, char* argv[]) { 16 int main(int argc, char* argv[]) {
17 17
18 - Redis rdx = {"localhost", 6379}; 18 + Redox rdx = {"localhost", 6379};
19 rdx.run(); 19 rdx.run();
20 // 20 //
21 // Command<int>* del_cmd = rdx.command_blocking<int>("DEL simple_loop:count"); 21 // Command<int>* del_cmd = rdx.command_blocking<int>("DEL simple_loop:count");
examples/simple_sync_loop.cpp
@@ -3,10 +3,10 @@ @@ -3,10 +3,10 @@
3 */ 3 */
4 4
5 #include <iostream> 5 #include <iostream>
6 -#include "../src/redisx.hpp" 6 +#include "../src/redox.hpp"
7 7
8 using namespace std; 8 using namespace std;
9 -using namespace redisx; 9 +using namespace redox;
10 10
11 double time_s() { 11 double time_s() {
12 unsigned long ms = chrono::system_clock::now().time_since_epoch() / chrono::microseconds(1); 12 unsigned long ms = chrono::system_clock::now().time_since_epoch() / chrono::microseconds(1);
@@ -15,7 +15,7 @@ double time_s() { @@ -15,7 +15,7 @@ double time_s() {
15 15
16 int main(int argc, char* argv[]) { 16 int main(int argc, char* argv[]) {
17 17
18 - Redis rdx = {"localhost", 6379}; 18 + Redox rdx = {"localhost", 6379};
19 rdx.run(); 19 rdx.run();
20 20
21 if(rdx.command_blocking("DEL simple_loop:count")) cout << "Deleted simple_loop:count" << endl; 21 if(rdx.command_blocking("DEL simple_loop:count")) cout << "Deleted simple_loop:count" << endl;
src/command.hpp
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 #include <hiredis/adapters/libev.h> 12 #include <hiredis/adapters/libev.h>
13 #include <hiredis/async.h> 13 #include <hiredis/async.h>
14 14
15 -namespace redisx { 15 +namespace redox {
16 16
17 static const int REDISX_UNINIT = -1; 17 static const int REDISX_UNINIT = -1;
18 static const int REDISX_OK = 0; 18 static const int REDISX_OK = 0;
@@ -25,7 +25,7 @@ static const int REDISX_TIMEOUT = 5; @@ -25,7 +25,7 @@ static const int REDISX_TIMEOUT = 5;
25 template<class ReplyT> 25 template<class ReplyT>
26 class Command { 26 class Command {
27 27
28 -friend class Redis; 28 +friend class Redox;
29 29
30 public: 30 public:
31 Command( 31 Command(
src/redisx.cpp renamed to src/redox.cpp
1 /** 1 /**
2 -* Redis C++11 wrapper. 2 +* Redox C++11 wrapper.
3 */ 3 */
4 4
5 #include <signal.h> 5 #include <signal.h>
6 #include <string.h> 6 #include <string.h>
7 -//#include <event2/thread.h>  
8 -#include "redisx.hpp" 7 +#include "redox.hpp"
9 8
10 using namespace std; 9 using namespace std;
11 10
12 -namespace redisx { 11 +namespace redox {
13 12
14 // Global mutex to manage waiting for connected state 13 // Global mutex to manage waiting for connected state
15 // TODO get rid of this as the only global variable? 14 // TODO get rid of this as the only global variable?
16 mutex connected_lock; 15 mutex connected_lock;
17 16
18 -/**  
19 -* Dummy function given to hiredis to use for freeing reply  
20 -* objects, so the memory can be managed here instead.  
21 -*/  
22 -void dummy_free_reply(void *reply) {}  
23 -  
24 -void connected(const redisAsyncContext *c, int status) { 17 +void Redox::connected(const redisAsyncContext *c, int status) {
25 if (status != REDIS_OK) { 18 if (status != REDIS_OK) {
26 cerr << "[ERROR] Connecting to Redis: " << c->errstr << endl; 19 cerr << "[ERROR] Connecting to Redis: " << c->errstr << endl;
27 return; 20 return;
28 } 21 }
29 22
30 - c->c.reader->fn->freeObject = dummy_free_reply; 23 + // Disable hiredis automatically freeing reply objects
  24 + c->c.reader->fn->freeObject = [](void* reply) {};
  25 +
31 cout << "Connected to Redis." << endl; 26 cout << "Connected to Redis." << endl;
32 connected_lock.unlock(); 27 connected_lock.unlock();
33 } 28 }
34 29
35 -void disconnected(const redisAsyncContext *c, int status) { 30 +void Redox::disconnected(const redisAsyncContext *c, int status) {
36 if (status != REDIS_OK) { 31 if (status != REDIS_OK) {
37 cerr << "[ERROR] Disconnecting from Redis: " << c->errstr << endl; 32 cerr << "[ERROR] Disconnecting from Redis: " << c->errstr << endl;
38 return; 33 return;
39 } 34 }
  35 +
  36 + // Re-enable hiredis automatically freeing reply objects
40 c->c.reader->fn->freeObject = freeReplyObject; 37 c->c.reader->fn->freeObject = freeReplyObject;
  38 +
41 cout << "Disconnected from Redis." << endl; 39 cout << "Disconnected from Redis." << endl;
42 connected_lock.lock(); 40 connected_lock.lock();
43 } 41 }
44 42
45 -Redis::Redis(const string& host, const int port) 43 +Redox::Redox(const string& host, const int port)
46 : host(host), port(port), cmd_count(0), to_exit(false) { 44 : host(host), port(port), cmd_count(0), to_exit(false) {
47 45
48 lock_guard<mutex> lg(queue_guard); 46 lock_guard<mutex> lg(queue_guard);
@@ -57,18 +55,18 @@ Redis::Redis(const string&amp; host, const int port) @@ -57,18 +55,18 @@ Redis::Redis(const string&amp; host, const int port)
57 } 55 }
58 56
59 redisLibevAttach(EV_DEFAULT_ c); 57 redisLibevAttach(EV_DEFAULT_ c);
60 - redisAsyncSetConnectCallback(c, connected);  
61 - redisAsyncSetDisconnectCallback(c, disconnected); 58 + redisAsyncSetConnectCallback(c, Redox::connected);
  59 + redisAsyncSetDisconnectCallback(c, Redox::disconnected);
62 } 60 }
63 61
64 -Redis::~Redis() { 62 +Redox::~Redox() {
65 redisAsyncDisconnect(c); 63 redisAsyncDisconnect(c);
66 stop(); 64 stop();
67 } 65 }
68 66
69 -void Redis::run_blocking() { 67 +void Redox::run_blocking() {
70 68
71 - // Events to connect to Redis 69 + // Events to connect to Redox
72 ev_run(EV_DEFAULT_ EVRUN_NOWAIT); 70 ev_run(EV_DEFAULT_ EVRUN_NOWAIT);
73 lock_guard<mutex> lg(connected_lock); 71 lock_guard<mutex> lg(connected_lock);
74 72
@@ -85,29 +83,57 @@ void Redis::run_blocking() { @@ -85,29 +83,57 @@ void Redis::run_blocking() {
85 exit_waiter.notify_one(); 83 exit_waiter.notify_one();
86 } 84 }
87 85
88 -void Redis::run() { 86 +void Redox::run() {
89 87
90 event_loop_thread = thread([this] { run_blocking(); }); 88 event_loop_thread = thread([this] { run_blocking(); });
91 event_loop_thread.detach(); 89 event_loop_thread.detach();
92 } 90 }
93 91
94 -void Redis::stop() { 92 +void Redox::stop() {
95 to_exit = true; 93 to_exit = true;
96 } 94 }
97 95
98 -void Redis::block() { 96 +void Redox::block() {
99 unique_lock<mutex> ul(exit_waiter_lock); 97 unique_lock<mutex> ul(exit_waiter_lock);
100 exit_waiter.wait(ul, [this]() { return to_exit.load(); }); 98 exit_waiter.wait(ul, [this]() { return to_exit.load(); });
101 } 99 }
102 100
  101 +template<class ReplyT>
  102 +void invoke_callback(
  103 + Command<ReplyT>* cmd_obj,
  104 + redisReply* reply
  105 +);
  106 +
  107 +template<class ReplyT>
  108 +void Redox::command_callback(redisAsyncContext *c, void *r, void *privdata) {
  109 +
  110 + auto *cmd_obj = (Command<ReplyT> *) privdata;
  111 + cmd_obj->reply_obj = (redisReply *) r;
  112 +
  113 + if (cmd_obj->reply_obj->type == REDIS_REPLY_ERROR) {
  114 + std::cerr << "[ERROR redisx.hpp:121] " << cmd_obj->cmd << ": " << cmd_obj->reply_obj->str << std::endl;
  115 + cmd_obj->invoke_error(REDISX_ERROR_REPLY);
  116 +
  117 + } else if(cmd_obj->reply_obj->type == REDIS_REPLY_NIL) {
  118 + std::cerr << "[WARNING] " << cmd_obj->cmd << ": Nil reply." << std::endl;
  119 + cmd_obj->invoke_error(REDISX_NIL_REPLY);
  120 +
  121 + } else {
  122 + invoke_callback<ReplyT>(cmd_obj, cmd_obj->reply_obj);
  123 + }
  124 +
  125 + // Free the reply object unless told not to
  126 + if(cmd_obj->free_memory) cmd_obj->free_reply_object();
  127 +}
  128 +
103 /** 129 /**
104 -* Submit an asynchronous command to the Redis server. Return 130 +* Submit an asynchronous command to the Redox server. Return
105 * true if succeeded, false otherwise. 131 * true if succeeded, false otherwise.
106 */ 132 */
107 template<class ReplyT> 133 template<class ReplyT>
108 bool submit_to_server(Command<ReplyT>* cmd_obj) { 134 bool submit_to_server(Command<ReplyT>* cmd_obj) {
109 cmd_obj->pending++; 135 cmd_obj->pending++;
110 - if (redisAsyncCommand(cmd_obj->c, command_callback<ReplyT>, (void*)cmd_obj, cmd_obj->cmd.c_str()) != REDIS_OK) { 136 + if (redisAsyncCommand(cmd_obj->c, Redox::command_callback<ReplyT>, (void*)cmd_obj, cmd_obj->cmd.c_str()) != REDIS_OK) {
111 cerr << "[ERROR] Could not send \"" << cmd_obj->cmd << "\": " << cmd_obj->c->errstr << endl; 137 cerr << "[ERROR] Could not send \"" << cmd_obj->cmd << "\": " << cmd_obj->c->errstr << endl;
112 cmd_obj->invoke_error(REDISX_SEND_ERROR); 138 cmd_obj->invoke_error(REDISX_SEND_ERROR);
113 return false; 139 return false;
@@ -129,7 +155,7 @@ void submit_command_callback(struct ev_loop* loop, ev_timer* timer, int revents) @@ -129,7 +155,7 @@ void submit_command_callback(struct ev_loop* loop, ev_timer* timer, int revents)
129 } 155 }
130 156
131 template<class ReplyT> 157 template<class ReplyT>
132 -bool Redis::process_queued_command(void* cmd_ptr) { 158 +bool Redox::process_queued_command(void* cmd_ptr) {
133 159
134 auto& command_map = get_command_map<ReplyT>(); 160 auto& command_map = get_command_map<ReplyT>();
135 161
@@ -153,7 +179,7 @@ bool Redis::process_queued_command(void* cmd_ptr) { @@ -153,7 +179,7 @@ bool Redis::process_queued_command(void* cmd_ptr) {
153 return true; 179 return true;
154 } 180 }
155 181
156 -void Redis::process_queued_commands() { 182 +void Redox::process_queued_commands() {
157 183
158 lock_guard<mutex> lg(queue_guard); 184 lock_guard<mutex> lg(queue_guard);
159 185
@@ -172,20 +198,24 @@ void Redis::process_queued_commands() { @@ -172,20 +198,24 @@ void Redis::process_queued_commands() {
172 } 198 }
173 } 199 }
174 200
175 -long Redis::num_commands_processed() { 201 +long Redox::num_commands_processed() {
176 lock_guard<mutex> lg(queue_guard); 202 lock_guard<mutex> lg(queue_guard);
177 return cmd_count; 203 return cmd_count;
178 } 204 }
179 205
180 // ---------------------------- 206 // ----------------------------
181 207
182 -template<> unordered_map<void*, Command<redisReply*>*>& Redis::get_command_map() { return commands_redis_reply; } 208 +template<> unordered_map<void*, Command<redisReply*>*>&
  209 +Redox::get_command_map() { return commands_redis_reply; }
  210 +
183 template<> 211 template<>
184 void invoke_callback(Command<redisReply*>* cmd_obj, redisReply* reply) { 212 void invoke_callback(Command<redisReply*>* cmd_obj, redisReply* reply) {
185 cmd_obj->invoke(reply); 213 cmd_obj->invoke(reply);
186 } 214 }
187 215
188 -template<> unordered_map<void*, Command<string>*>& Redis::get_command_map() { return commands_string_r; } 216 +template<> unordered_map<void*, Command<string>*>&
  217 +Redox::get_command_map() { return commands_string_r; }
  218 +
189 template<> 219 template<>
190 void invoke_callback(Command<string>* cmd_obj, redisReply* reply) { 220 void invoke_callback(Command<string>* cmd_obj, redisReply* reply) {
191 if(reply->type != REDIS_REPLY_STRING && reply->type != REDIS_REPLY_STATUS) { 221 if(reply->type != REDIS_REPLY_STRING && reply->type != REDIS_REPLY_STATUS) {
@@ -198,7 +228,9 @@ void invoke_callback(Command&lt;string&gt;* cmd_obj, redisReply* reply) { @@ -198,7 +228,9 @@ void invoke_callback(Command&lt;string&gt;* cmd_obj, redisReply* reply) {
198 cmd_obj->invoke(s); 228 cmd_obj->invoke(s);
199 } 229 }
200 230
201 -template<> unordered_map<void*, Command<char*>*>& Redis::get_command_map() { return commands_char_p; } 231 +template<> unordered_map<void*, Command<char*>*>&
  232 +Redox::get_command_map() { return commands_char_p; }
  233 +
202 template<> 234 template<>
203 void invoke_callback(Command<char*>* cmd_obj, redisReply* reply) { 235 void invoke_callback(Command<char*>* cmd_obj, redisReply* reply) {
204 if(reply->type != REDIS_REPLY_STRING && reply->type != REDIS_REPLY_STATUS) { 236 if(reply->type != REDIS_REPLY_STRING && reply->type != REDIS_REPLY_STATUS) {
@@ -209,7 +241,9 @@ void invoke_callback(Command&lt;char*&gt;* cmd_obj, redisReply* reply) { @@ -209,7 +241,9 @@ void invoke_callback(Command&lt;char*&gt;* cmd_obj, redisReply* reply) {
209 cmd_obj->invoke(reply->str); 241 cmd_obj->invoke(reply->str);
210 } 242 }
211 243
212 -template<> unordered_map<void*, Command<int>*>& Redis::get_command_map() { return commands_int; } 244 +template<> unordered_map<void*, Command<int>*>&
  245 +Redox::get_command_map() { return commands_int; }
  246 +
213 template<> 247 template<>
214 void invoke_callback(Command<int>* cmd_obj, redisReply* reply) { 248 void invoke_callback(Command<int>* cmd_obj, redisReply* reply) {
215 if(reply->type != REDIS_REPLY_INTEGER) { 249 if(reply->type != REDIS_REPLY_INTEGER) {
@@ -220,7 +254,9 @@ void invoke_callback(Command&lt;int&gt;* cmd_obj, redisReply* reply) { @@ -220,7 +254,9 @@ void invoke_callback(Command&lt;int&gt;* cmd_obj, redisReply* reply) {
220 cmd_obj->invoke((int)reply->integer); 254 cmd_obj->invoke((int)reply->integer);
221 } 255 }
222 256
223 -template<> unordered_map<void*, Command<long long int>*>& Redis::get_command_map() { return commands_long_long_int; } 257 +template<> unordered_map<void*, Command<long long int>*>&
  258 +Redox::get_command_map() { return commands_long_long_int; }
  259 +
224 template<> 260 template<>
225 void invoke_callback(Command<long long int>* cmd_obj, redisReply* reply) { 261 void invoke_callback(Command<long long int>* cmd_obj, redisReply* reply) {
226 if(reply->type != REDIS_REPLY_INTEGER) { 262 if(reply->type != REDIS_REPLY_INTEGER) {
@@ -235,11 +271,11 @@ void invoke_callback(Command&lt;long long int&gt;* cmd_obj, redisReply* reply) { @@ -235,11 +271,11 @@ void invoke_callback(Command&lt;long long int&gt;* cmd_obj, redisReply* reply) {
235 // Helpers 271 // Helpers
236 // ---------------------------- 272 // ----------------------------
237 273
238 -void Redis::command(const string& cmd) { 274 +void Redox::command(const string& cmd) {
239 command<redisReply*>(cmd, NULL); 275 command<redisReply*>(cmd, NULL);
240 } 276 }
241 277
242 -bool Redis::command_blocking(const string& cmd) { 278 +bool Redox::command_blocking(const string& cmd) {
243 Command<redisReply*>* c = command_blocking<redisReply*>(cmd); 279 Command<redisReply*>* c = command_blocking<redisReply*>(cmd);
244 bool succeeded = (c->status() == REDISX_OK); 280 bool succeeded = (c->status() == REDISX_OK);
245 c->free(); 281 c->free();
src/redisx.hpp renamed to src/redox.hpp
1 /** 1 /**
2 -* Redis C++11 wrapper. 2 +* Redox C++11 wrapper.
3 */ 3 */
4 4
5 #pragma once 5 #pragma once
@@ -22,14 +22,14 @@ @@ -22,14 +22,14 @@
22 22
23 #include "command.hpp" 23 #include "command.hpp"
24 24
25 -namespace redisx { 25 +namespace redox {
26 26
27 -class Redis { 27 +class Redox {
28 28
29 public: 29 public:
30 30
31 - Redis(const std::string& host, const int port);  
32 - ~Redis(); 31 + Redox(const std::string& host, const int port);
  32 + ~Redox();
33 33
34 void run(); 34 void run();
35 void run_blocking(); 35 void run_blocking();
@@ -57,13 +57,19 @@ public: @@ -57,13 +57,19 @@ public:
57 57
58 long num_commands_processed(); 58 long num_commands_processed();
59 59
  60 + template<class ReplyT>
  61 + static void command_callback(redisAsyncContext *c, void *r, void *privdata);
  62 +
  63 + static void connected(const redisAsyncContext *c, int status);
  64 + static void disconnected(const redisAsyncContext *c, int status);
  65 +
60 // void publish(std::string channel, std::string msg); 66 // void publish(std::string channel, std::string msg);
61 // void subscribe(std::string channel, std::function<void(std::string channel, std::string msg)> callback); 67 // void subscribe(std::string channel, std::function<void(std::string channel, std::string msg)> callback);
62 // void unsubscribe(std::string channel); 68 // void unsubscribe(std::string channel);
63 69
64 private: 70 private:
65 71
66 - // Redis server 72 + // Redox server
67 std::string host; 73 std::string host;
68 int port; 74 int port;
69 75
@@ -98,35 +104,7 @@ private: @@ -98,35 +104,7 @@ private:
98 // --------------------------- 104 // ---------------------------
99 105
100 template<class ReplyT> 106 template<class ReplyT>
101 -void invoke_callback(  
102 - Command<ReplyT>* cmd_obj,  
103 - redisReply* reply  
104 -);  
105 -  
106 -template<class ReplyT>  
107 -void command_callback(redisAsyncContext *c, void *r, void *privdata) {  
108 -  
109 - auto *cmd_obj = (Command<ReplyT> *) privdata;  
110 - cmd_obj->reply_obj = (redisReply *) r;  
111 -  
112 - if (cmd_obj->reply_obj->type == REDIS_REPLY_ERROR) {  
113 - std::cerr << "[ERROR redisx.hpp:121] " << cmd_obj->cmd << ": " << cmd_obj->reply_obj->str << std::endl;  
114 - cmd_obj->invoke_error(REDISX_ERROR_REPLY);  
115 -  
116 - } else if(cmd_obj->reply_obj->type == REDIS_REPLY_NIL) {  
117 - std::cerr << "[WARNING] " << cmd_obj->cmd << ": Nil reply." << std::endl;  
118 - cmd_obj->invoke_error(REDISX_NIL_REPLY);  
119 -  
120 - } else {  
121 - invoke_callback<ReplyT>(cmd_obj, cmd_obj->reply_obj);  
122 - }  
123 -  
124 - // Free the reply object unless told not to  
125 - if(cmd_obj->free_memory) cmd_obj->free_reply_object();  
126 -}  
127 -  
128 -template<class ReplyT>  
129 -Command<ReplyT>* Redis::command( 107 +Command<ReplyT>* Redox::command(
130 const std::string& cmd, 108 const std::string& cmd,
131 const std::function<void(const std::string&, const ReplyT&)>& callback, 109 const std::function<void(const std::string&, const ReplyT&)>& callback,
132 const std::function<void(const std::string&, int status)>& error_callback, 110 const std::function<void(const std::string&, int status)>& error_callback,
@@ -142,7 +120,7 @@ Command&lt;ReplyT&gt;* Redis::command( @@ -142,7 +120,7 @@ Command&lt;ReplyT&gt;* Redis::command(
142 } 120 }
143 121
144 template<class ReplyT> 122 template<class ReplyT>
145 -bool Redis::cancel(Command<ReplyT>* cmd_obj) { 123 +bool Redox::cancel(Command<ReplyT>* cmd_obj) {
146 124
147 if(cmd_obj == NULL) { 125 if(cmd_obj == NULL) {
148 std::cerr << "[ERROR] Canceling null command." << std::endl; 126 std::cerr << "[ERROR] Canceling null command." << std::endl;
@@ -161,7 +139,7 @@ bool Redis::cancel(Command&lt;ReplyT&gt;* cmd_obj) { @@ -161,7 +139,7 @@ bool Redis::cancel(Command&lt;ReplyT&gt;* cmd_obj) {
161 } 139 }
162 140
163 template<class ReplyT> 141 template<class ReplyT>
164 -Command<ReplyT>* Redis::command_blocking(const std::string& cmd) { 142 +Command<ReplyT>* Redox::command_blocking(const std::string& cmd) {
165 143
166 ReplyT val; 144 ReplyT val;
167 std::atomic_int status(REDISX_UNINIT); 145 std::atomic_int status(REDISX_UNINIT);