EV-Hiredis
view release on metacpan or search on metacpan
src/EV__Hiredis.xs view on Meta::CPAN
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "EVAPI.h"
#include "hiredis.h"
#include "async.h"
#include "libev_adapter.h"
#include "ngx-queue.h"
typedef struct ev_hiredis_s ev_hiredis_t;
typedef struct ev_hiredis_cb_s ev_hiredis_cb_t;
typedef ev_hiredis_t* EV__Hiredis;
typedef struct ev_loop* EV__Loop;
struct ev_hiredis_s {
struct ev_loop* loop;
redisAsyncContext* ac;
SV* error_handler;
SV* connect_handler;
struct timeval* connect_timeout;
struct timeval* command_timeout;
ngx_queue_t cb_queue; /* for long term callbacks such as subscribe */
};
struct ev_hiredis_cb_s {
SV* cb;
ngx_queue_t queue;
int persist;
};
static void emit_error(EV__Hiredis self, SV* error) {
if (NULL == self->error_handler) return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(error);
PUTBACK;
call_sv(self->error_handler, G_DISCARD);
FREETMPS;
LEAVE;
}
static void emit_error_str(EV__Hiredis self, char* error) {
if (NULL == self->error_handler) return;
emit_error(self, sv_2mortal(newSVpv(error, 0)));
}
static void remove_cb_queue(EV__Hiredis self) {
ngx_queue_t* q;
ev_hiredis_cb_t* cbt;
while (!ngx_queue_empty(&self->cb_queue)) {
q = ngx_queue_last(&self->cb_queue);
cbt = ngx_queue_data(q, ev_hiredis_cb_t, queue);
ngx_queue_remove(q);
SvREFCNT_dec(cbt->cb);
Safefree(cbt);
}
}
static void EV__hiredis_connect_cb(redisAsyncContext* c, int status) {
EV__Hiredis self = (EV__Hiredis)c->data;
if (REDIS_OK != status) {
self->ac = NULL;
emit_error_str(self, c->errstr);
}
else {
if (NULL == self->connect_handler) return;
dSP;
ENTER;
SAVETMPS;
( run in 0.500 second using v1.01-cache-2.11-cpan-98e64b0badf )