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 1 cmake_minimum_required(VERSION 2.8.4)
2   -project(redisx)
  2 +project(redox)
3 3  
4 4 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wall -O3")
5 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 12 set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
13 13  
14 14 set(SRC_CORE
15   - ${SRC_DIR}/redisx.cpp
  15 + ${SRC_DIR}/redox.cpp
16 16 )
17 17  
18 18 set(SRC_ALL ${SRC_CORE})
... ...
examples/simple_loop.cpp
... ... @@ -3,10 +3,10 @@
3 3 */
4 4  
5 5 #include <iostream>
6   -#include "../src/redisx.hpp"
  6 +#include "../src/redox.hpp"
7 7  
8 8 using namespace std;
9   -using namespace redisx;
  9 +using namespace redox;
10 10  
11 11 double time_s() {
12 12 unsigned long ms = chrono::system_clock::now().time_since_epoch() / chrono::microseconds(1);
... ... @@ -15,7 +15,7 @@ double time_s() {
15 15  
16 16 int main(int argc, char* argv[]) {
17 17  
18   - Redis rdx = {"localhost", 6379};
  18 + Redox rdx = {"localhost", 6379};
19 19 rdx.run();
20 20 //
21 21 // Command<int>* del_cmd = rdx.command_blocking<int>("DEL simple_loop:count");
... ...
examples/simple_sync_loop.cpp
... ... @@ -3,10 +3,10 @@
3 3 */
4 4  
5 5 #include <iostream>
6   -#include "../src/redisx.hpp"
  6 +#include "../src/redox.hpp"
7 7  
8 8 using namespace std;
9   -using namespace redisx;
  9 +using namespace redox;
10 10  
11 11 double time_s() {
12 12 unsigned long ms = chrono::system_clock::now().time_since_epoch() / chrono::microseconds(1);
... ... @@ -15,7 +15,7 @@ double time_s() {
15 15  
16 16 int main(int argc, char* argv[]) {
17 17  
18   - Redis rdx = {"localhost", 6379};
  18 + Redox rdx = {"localhost", 6379};
19 19 rdx.run();
20 20  
21 21 if(rdx.command_blocking("DEL simple_loop:count")) cout << "Deleted simple_loop:count" << endl;
... ...
src/command.hpp
... ... @@ -12,7 +12,7 @@
12 12 #include <hiredis/adapters/libev.h>
13 13 #include <hiredis/async.h>
14 14  
15   -namespace redisx {
  15 +namespace redox {
16 16  
17 17 static const int REDISX_UNINIT = -1;
18 18 static const int REDISX_OK = 0;
... ... @@ -25,7 +25,7 @@ static const int REDISX_TIMEOUT = 5;
25 25 template<class ReplyT>
26 26 class Command {
27 27  
28   -friend class Redis;
  28 +friend class Redox;
29 29  
30 30 public:
31 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 5 #include <signal.h>
6 6 #include <string.h>
7   -//#include <event2/thread.h>
8   -#include "redisx.hpp"
  7 +#include "redox.hpp"
9 8  
10 9 using namespace std;
11 10  
12   -namespace redisx {
  11 +namespace redox {
13 12  
14 13 // Global mutex to manage waiting for connected state
15 14 // TODO get rid of this as the only global variable?
16 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 18 if (status != REDIS_OK) {
26 19 cerr << "[ERROR] Connecting to Redis: " << c->errstr << endl;
27 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 26 cout << "Connected to Redis." << endl;
32 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 31 if (status != REDIS_OK) {
37 32 cerr << "[ERROR] Disconnecting from Redis: " << c->errstr << endl;
38 33 return;
39 34 }
  35 +
  36 + // Re-enable hiredis automatically freeing reply objects
40 37 c->c.reader->fn->freeObject = freeReplyObject;
  38 +
41 39 cout << "Disconnected from Redis." << endl;
42 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 44 : host(host), port(port), cmd_count(0), to_exit(false) {
47 45  
48 46 lock_guard<mutex> lg(queue_guard);
... ... @@ -57,18 +55,18 @@ Redis::Redis(const string&amp; host, const int port)
57 55 }
58 56  
59 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 63 redisAsyncDisconnect(c);
66 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 70 ev_run(EV_DEFAULT_ EVRUN_NOWAIT);
73 71 lock_guard<mutex> lg(connected_lock);
74 72  
... ... @@ -85,29 +83,57 @@ void Redis::run_blocking() {
85 83 exit_waiter.notify_one();
86 84 }
87 85  
88   -void Redis::run() {
  86 +void Redox::run() {
89 87  
90 88 event_loop_thread = thread([this] { run_blocking(); });
91 89 event_loop_thread.detach();
92 90 }
93 91  
94   -void Redis::stop() {
  92 +void Redox::stop() {
95 93 to_exit = true;
96 94 }
97 95  
98   -void Redis::block() {
  96 +void Redox::block() {
99 97 unique_lock<mutex> ul(exit_waiter_lock);
100 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 131 * true if succeeded, false otherwise.
106 132 */
107 133 template<class ReplyT>
108 134 bool submit_to_server(Command<ReplyT>* cmd_obj) {
109 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 137 cerr << "[ERROR] Could not send \"" << cmd_obj->cmd << "\": " << cmd_obj->c->errstr << endl;
112 138 cmd_obj->invoke_error(REDISX_SEND_ERROR);
113 139 return false;
... ... @@ -129,7 +155,7 @@ void submit_command_callback(struct ev_loop* loop, ev_timer* timer, int revents)
129 155 }
130 156  
131 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 160 auto& command_map = get_command_map<ReplyT>();
135 161  
... ... @@ -153,7 +179,7 @@ bool Redis::process_queued_command(void* cmd_ptr) {
153 179 return true;
154 180 }
155 181  
156   -void Redis::process_queued_commands() {
  182 +void Redox::process_queued_commands() {
157 183  
158 184 lock_guard<mutex> lg(queue_guard);
159 185  
... ... @@ -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 202 lock_guard<mutex> lg(queue_guard);
177 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 211 template<>
184 212 void invoke_callback(Command<redisReply*>* cmd_obj, redisReply* reply) {
185 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 219 template<>
190 220 void invoke_callback(Command<string>* cmd_obj, redisReply* reply) {
191 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 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 234 template<>
203 235 void invoke_callback(Command<char*>* cmd_obj, redisReply* reply) {
204 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 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 247 template<>
214 248 void invoke_callback(Command<int>* cmd_obj, redisReply* reply) {
215 249 if(reply->type != REDIS_REPLY_INTEGER) {
... ... @@ -220,7 +254,9 @@ void invoke_callback(Command&lt;int&gt;* cmd_obj, redisReply* reply) {
220 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 260 template<>
225 261 void invoke_callback(Command<long long int>* cmd_obj, redisReply* reply) {
226 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 271 // Helpers
236 272 // ----------------------------
237 273  
238   -void Redis::command(const string& cmd) {
  274 +void Redox::command(const string& cmd) {
239 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 279 Command<redisReply*>* c = command_blocking<redisReply*>(cmd);
244 280 bool succeeded = (c->status() == REDISX_OK);
245 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 5 #pragma once
... ... @@ -22,14 +22,14 @@
22 22  
23 23 #include "command.hpp"
24 24  
25   -namespace redisx {
  25 +namespace redox {
26 26  
27   -class Redis {
  27 +class Redox {
28 28  
29 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 34 void run();
35 35 void run_blocking();
... ... @@ -57,13 +57,19 @@ public:
57 57  
58 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 66 // void publish(std::string channel, std::string msg);
61 67 // void subscribe(std::string channel, std::function<void(std::string channel, std::string msg)> callback);
62 68 // void unsubscribe(std::string channel);
63 69  
64 70 private:
65 71  
66   - // Redis server
  72 + // Redox server
67 73 std::string host;
68 74 int port;
69 75  
... ... @@ -98,35 +104,7 @@ private:
98 104 // ---------------------------
99 105  
100 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 108 const std::string& cmd,
131 109 const std::function<void(const std::string&, const ReplyT&)>& callback,
132 110 const std::function<void(const std::string&, int status)>& error_callback,
... ... @@ -142,7 +120,7 @@ Command&lt;ReplyT&gt;* Redis::command(
142 120 }
143 121  
144 122 template<class ReplyT>
145   -bool Redis::cancel(Command<ReplyT>* cmd_obj) {
  123 +bool Redox::cancel(Command<ReplyT>* cmd_obj) {
146 124  
147 125 if(cmd_obj == NULL) {
148 126 std::cerr << "[ERROR] Canceling null command." << std::endl;
... ... @@ -161,7 +139,7 @@ bool Redis::cancel(Command&lt;ReplyT&gt;* cmd_obj) {
161 139 }
162 140  
163 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 144 ReplyT val;
167 145 std::atomic_int status(REDISX_UNINIT);
... ...