From f15350940969f0fbe2939719c00fe3a1426c3a2c Mon Sep 17 00:00:00 2001 From: Gregory Burd Date: Wed, 31 Jul 2013 15:39:55 -0400 Subject: [PATCH] With some input from Jon I've managed to reduce this back into a macro rather than a fun and a macro calling a fun. He also suggested that on eagain I sleep a small amount of time so as to allow other work to catch up a bit. --- src/async_nif.hrl | 48 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/async_nif.hrl b/src/async_nif.hrl index 44b7a2a..d7b5bee 100644 --- a/src/async_nif.hrl +++ b/src/async_nif.hrl @@ -21,28 +21,26 @@ %% %% ------------------------------------------------------------------- --spec async_nif_enqueue(function(), [term()]) -> term() | {error, term()}. -async_nif_enqueue(F, A) -> - R = erlang:make_ref(), - case erlang:apply(F, [R|A]) of - {ok, enqueued} -> - receive - {R, {error, shutdown}=Error} -> - %% Work unit was queued, but not executed. - Error; - {R, {error, _Reason}=Error} -> - %% Work unit returned an error. - Error; - {R, Reply} -> - Reply - end; - {error, eagain} -> - %% Work unit was not queued, try again. - async_nif_enqueue(F, A); - %{error, enomem} -> - %{error, shutdown} -> - Other -> - Other - end. - --define(ASYNC_NIF_CALL(Fun, Args), async_nif_enqueue(Fun, Args)). +-define(ASYNC_NIF_CALL(Fun, Args), + F = fun(F, A, R, T) -> + case erlang:apply(F, [R|A]) of + {ok, enqueued} -> + receive + {R, {error, shutdown}=Error} -> + %% Work unit was queued, but not executed. + Error; + {R, {error, _Reason}=Error} -> + %% Work unit returned an error. + Error; + {R, Reply} -> + Reply + end; + {error, eagain} -> + SleepyTime = min(30, (T+1)*2), + timer:sleep(SleepyTime), + F(F, A, R, SleepyTime); + Other -> + Other + end + end, + F(Fun, Args, erlang:make_ref(), 1)).