hiredis icon indicating copy to clipboard operation
hiredis copied to clipboard

asynchronous by libevent doesn't works

Open mz02005 opened this issue 3 years ago • 4 comments

here is my first version based on example-libevent.c, and it works(means all callback functions are called).

	struct event_base *base = event_base_new();

	redisOptions options = { 0 };
	REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379);
	struct timeval tv = { 0 };
	tv.tv_sec = 10;
	options.timeout = &tv;

	redisAsyncContext *c = redisAsyncConnectWithOptions(&options);
	if (c->err) {
		/* Let *c leak for now... */
		printf("Error: %s\n", c->errstr);
		return 1;
	}

	redisLibeventAttach(c, base);
	redisAsyncSetConnectCallback(c, connectCallback);
	redisAsyncSetDisconnectCallback(c, disconnectCallback);
	redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc - 1], strlen(argv[argc - 1]));
	redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");

	std::thread newThread([base]()
	{
		event_base_loop(base, EVLOOP_NO_EXIT_ON_EMPTY);
	});

	if (newThread.joinable())
		newThread.join();

then i moved the thread creation statements to the above and it doesn't works

	struct event_base *base = event_base_new();

	std::thread newThread([base]()
	{
		event_base_loop(base, EVLOOP_NO_EXIT_ON_EMPTY);
	});

	redisOptions options = { 0 };
	REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379);
	struct timeval tv = { 0 };
	tv.tv_sec = 10;
	options.timeout = &tv;

	redisAsyncContext *c = redisAsyncConnectWithOptions(&options);
	if (c->err) {
		/* Let *c leak for now... */
		printf("Error: %s\n", c->errstr);
		return 1;
	}

	redisLibeventAttach(c, base);
	redisAsyncSetConnectCallback(c, connectCallback);
	redisAsyncSetDisconnectCallback(c, disconnectCallback);
	redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc - 1], strlen(argv[argc - 1]));
	redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");

	if (newThread.joinable())
		newThread.join();

i have tested the vcpkg version(2019-11-2) and github version on 2020-11-26

mz02005 avatar Nov 27 '20 01:11 mz02005

Hi @mz02005,

I'm more familiar with libev but you're trying to send commands into the event loop from a different thread. Generally this is not correct, because both threads will be attempting to interact with the Hiredis' internals and hiredis doesn't have any synchronization logic.

Generally what you should do is set up timers or other callback based mechanisms and then message the event loop to act when you've got data to process.

Since we get similar questions somewhat frequently I'll put together a more robust example that involves more than just setting up the event loop.

michael-grunder avatar Dec 12 '20 22:12 michael-grunder

@michael-grunder Can I confirm that the adapters are more of an example then? Cause to your point, as the adapters are written now the event loop examples only work due to fact that the event loop is spawned after sending commands. The loops themselves do not seem to have any queuing mechanism for getting new commands into the event loop (or maybe they do, I have limited knowledge of the even libs). So I guess its expected for the developer to build their own event lib hooks that incorporate the queueing? If so, it might be good enough to just call this out in the readme.

jm4games avatar Apr 11 '21 15:04 jm4games

@jm4games Yes, none of the examples really show "real-world" use where the event loop processes events received over a longer period of time. They're all mostly one-shot examples where a few events are fired and then processed.

One complication is that the different event libraries will have different semantics for acting on events, but I still think a more realistic example would be useful. Honestly, I just haven't gotten around to creating one yet.

michael-grunder avatar Apr 12 '21 18:04 michael-grunder

Yeah fully understand the time thing. Thanks for the confirmation. As I mentioned since you are short on time, it might be good enough for now just to call this out in the readme so that developers have appropriate expectations. I do know this has caused some confusion for people.

jm4games avatar Apr 12 '21 18:04 jm4games

Closing this issue as it's not really a bug in Hiredis. I will still try to create a more robust async example in the future, however.

michael-grunder avatar Sep 01 '22 03:09 michael-grunder