Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
hiredis
Commits
e3776bfa
Commit
e3776bfa
authored
Dec 28, 2010
by
Pieter Noordhuis
Browse files
Add function to explicitly free an async context
parent
3d76f3fe
Changes
4
Show whitespace changes
Inline
Side-by-side
async.c
View file @
e3776bfa
...
...
@@ -151,6 +151,39 @@ static int __redisShiftCallback(redisCallbackList *list, redisCallback *target)
return
REDIS_ERR
;
}
/* Helper function to free the context. */
static
void
__redisAsyncFree
(
redisAsyncContext
*
ac
)
{
redisContext
*
c
=
&
(
ac
->
c
);
/* Clear callback list */
while
(
__redisShiftCallback
(
&
ac
->
replies
,
NULL
)
==
REDIS_OK
);
/* Signal event lib to clean up */
if
(
ac
->
evCleanup
)
ac
->
evCleanup
(
ac
->
_adapter_data
);
/* Execute callback with proper status */
if
(
ac
->
onDisconnect
&&
(
c
->
flags
&
REDIS_CONNECTED
))
ac
->
onDisconnect
(
ac
,
(
ac
->
err
==
0
)
?
REDIS_OK
:
REDIS_ERR
);
/* Cleanup self */
redisFree
(
c
);
}
/* Free's the async context. When REDIS_CONNECTED is set, it could only have
* been called from a command callback so we need to let control return to
* redisProcessCallbacks() before free'ing can continue.
*
* When REDIS_CONNECTED is not set, the first write event has not yet fired and
* we can free immediately. */
void
redisAsyncFree
(
redisAsyncContext
*
ac
)
{
redisContext
*
c
=
&
(
ac
->
c
);
if
(
c
->
flags
&
REDIS_CONNECTED
)
{
c
->
flags
|=
REDIS_FREEING
;
}
else
{
__redisAsyncFree
(
ac
);
}
}
/* Tries to do a clean disconnect from Redis, meaning it stops new commands
* from being issued, but tries to flush the output buffer and execute
* callbacks for all remaining replies.
...
...
@@ -167,13 +200,11 @@ void redisAsyncDisconnect(redisAsyncContext *ac) {
static
void
__redisAsyncDisconnect
(
redisAsyncContext
*
ac
)
{
redisContext
*
c
=
&
(
ac
->
c
);
redisCallback
cb
;
int
status
;
/* Make sure error is accessible if there is any */
__redisAsyncCopyError
(
ac
);
status
=
(
ac
->
err
==
0
)
?
REDIS_OK
:
REDIS_ERR
;
if
(
status
==
REDIS_OK
)
{
if
(
ac
->
err
==
0
)
{
/* When the connection is cleanly disconnected, there should not
* be pending callbacks. */
assert
(
__redisShiftCallback
(
&
ac
->
replies
,
NULL
)
==
REDIS_ERR
);
...
...
@@ -188,14 +219,7 @@ static void __redisAsyncDisconnect(redisAsyncContext *ac) {
}
}
/* Signal event lib to clean up */
if
(
ac
->
evCleanup
)
ac
->
evCleanup
(
ac
->
_adapter_data
);
/* Execute callback with proper status */
if
(
ac
->
onDisconnect
)
ac
->
onDisconnect
(
ac
,
status
);
/* Cleanup self */
redisFree
(
c
);
__redisAsyncFree
(
ac
);
}
void
redisProcessCallbacks
(
redisAsyncContext
*
ac
)
{
...
...
@@ -225,6 +249,12 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
}
else
{
c
->
fn
->
freeObject
(
reply
);
}
/* Proceed with free'ing when redisAsyncFree() was called. */
if
(
c
->
flags
&
REDIS_FREEING
)
{
__redisAsyncFree
(
ac
);
return
;
}
}
/* Disconnect when there was an error reading the reply */
...
...
@@ -281,8 +311,8 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
redisContext
*
c
=
&
(
ac
->
c
);
redisCallback
cb
;
/* Don't accept new commands when the connection is
lazily
closed. */
if
(
c
->
flags
&
REDIS_DISCONNECTING
)
return
REDIS_ERR
;
/* Don't accept new commands when the connection is
about to be
closed. */
if
(
c
->
flags
&
(
REDIS_DISCONNECTING
|
REDIS_FREEING
)
)
return
REDIS_ERR
;
__redisAppendCommand
(
c
,
cmd
,
len
);
/* Store callback */
...
...
async.h
View file @
e3776bfa
...
...
@@ -95,6 +95,7 @@ int redisAsyncSetReplyObjectFunctions(redisAsyncContext *ac, redisReplyObjectFun
int
redisAsyncSetConnectCallback
(
redisAsyncContext
*
ac
,
redisConnectCallback
*
fn
);
int
redisAsyncSetDisconnectCallback
(
redisAsyncContext
*
ac
,
redisDisconnectCallback
*
fn
);
void
redisAsyncDisconnect
(
redisAsyncContext
*
ac
);
void
redisAsyncFree
(
redisAsyncContext
*
ac
);
/* Handle read/write events */
void
redisAsyncHandleRead
(
redisAsyncContext
*
ac
);
...
...
hiredis.c
View file @
e3776bfa
...
...
@@ -809,8 +809,7 @@ static redisContext *redisContextInit() {
}
void
redisFree
(
redisContext
*
c
)
{
/* Disconnect before free'ing if not yet disconnected. */
if
(
c
->
flags
&
REDIS_CONNECTED
)
if
(
c
->
fd
>
0
)
close
(
c
->
fd
);
if
(
c
->
errstr
!=
NULL
)
sdsfree
(
c
->
errstr
);
...
...
hiredis.h
View file @
e3776bfa
...
...
@@ -64,6 +64,10 @@
* should be terminated once all replies have been read. */
#define REDIS_DISCONNECTING 0x4
/* Flag specific to the async API which means that the context should be clean
* up as soon as possible. */
#define REDIS_FREEING 0x8
#define REDIS_REPLY_STRING 1
#define REDIS_REPLY_ARRAY 2
#define REDIS_REPLY_INTEGER 3
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment