1 /*-
2  * Copyright (C) 2014 Pietro Cerutti <[email protected]>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #ifndef __HIREDIS_QT_H__
27 #define __HIREDIS_QT_H__
28 #include <QSocketNotifier>
29 #include "../async.h"
30 
31 static void RedisQtAddRead(void *);
32 static void RedisQtDelRead(void *);
33 static void RedisQtAddWrite(void *);
34 static void RedisQtDelWrite(void *);
35 static void RedisQtCleanup(void *);
36 
37 class RedisQtAdapter : public QObject {
38 
39     Q_OBJECT
40 
41     friend
RedisQtAddRead(void * adapter)42     void RedisQtAddRead(void * adapter) {
43         RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
44         a->addRead();
45     }
46 
47     friend
RedisQtDelRead(void * adapter)48     void RedisQtDelRead(void * adapter) {
49         RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
50         a->delRead();
51     }
52 
53     friend
RedisQtAddWrite(void * adapter)54     void RedisQtAddWrite(void * adapter) {
55         RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
56         a->addWrite();
57     }
58 
59     friend
RedisQtDelWrite(void * adapter)60     void RedisQtDelWrite(void * adapter) {
61         RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
62         a->delWrite();
63     }
64 
65     friend
RedisQtCleanup(void * adapter)66     void RedisQtCleanup(void * adapter) {
67         RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
68         a->cleanup();
69     }
70 
71     public:
72         RedisQtAdapter(QObject * parent = 0)
QObject(parent)73             : QObject(parent), m_ctx(0), m_read(0), m_write(0) { }
74 
~RedisQtAdapter()75         ~RedisQtAdapter() {
76             if (m_ctx != 0) {
77                 m_ctx->ev.data = NULL;
78             }
79         }
80 
setContext(redisAsyncContext * ac)81         int setContext(redisAsyncContext * ac) {
82             if (ac->ev.data != NULL) {
83                 return REDIS_ERR;
84             }
85             m_ctx = ac;
86             m_ctx->ev.data = this;
87             m_ctx->ev.addRead = RedisQtAddRead;
88             m_ctx->ev.delRead = RedisQtDelRead;
89             m_ctx->ev.addWrite = RedisQtAddWrite;
90             m_ctx->ev.delWrite = RedisQtDelWrite;
91             m_ctx->ev.cleanup = RedisQtCleanup;
92             return REDIS_OK;
93         }
94 
95     private:
addRead()96         void addRead() {
97             if (m_read) return;
98             m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 0);
99             connect(m_read, SIGNAL(activated(int)), this, SLOT(read()));
100         }
101 
delRead()102         void delRead() {
103             if (!m_read) return;
104             delete m_read;
105             m_read = 0;
106         }
107 
addWrite()108         void addWrite() {
109             if (m_write) return;
110             m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 0);
111             connect(m_write, SIGNAL(activated(int)), this, SLOT(write()));
112         }
113 
delWrite()114         void delWrite() {
115             if (!m_write) return;
116             delete m_write;
117             m_write = 0;
118         }
119 
cleanup()120         void cleanup() {
121             delRead();
122             delWrite();
123         }
124 
125     private slots:
read()126         void read() { redisAsyncHandleRead(m_ctx); }
write()127         void write() { redisAsyncHandleWrite(m_ctx); }
128 
129     private:
130         redisAsyncContext * m_ctx;
131         QSocketNotifier * m_read;
132         QSocketNotifier * m_write;
133 };
134 
135 #endif /* !__HIREDIS_QT_H__ */
136