11#include <stdlib.h>
2+ #include <assert.h>
23#include <ev.h>
34#include <dispatch/dispatch.h>
45
@@ -14,8 +15,9 @@ static int queue_length = 10;
1415static main_async_t * async_queue ;
1516static ev_async main_async ;
1617
17- void dispatch_main_async_f (void * context , void (* cb )(void * ))
18+ void main_async_f (void * context , void (* cb )(void * ))
1819{
20+ assert (cb );
1921 dispatch_semaphore_wait (async_queue_semaphore , DISPATCH_TIME_FOREVER );
2022 ++ queue_pending ;
2123 if (queue_pending > queue_length )
@@ -30,14 +32,20 @@ void dispatch_main_async_f(void* context, void (*cb)(void*))
3032 ev_async_send (EV_DEFAULT_ & main_async );
3133}
3234
33- static void main_async_dispatch (EV_P_ ev_async * w , int revents )
35+ static void main_async_drain (EV_P_ ev_async * w , int revents )
3436{
3537 dispatch_semaphore_wait (async_queue_semaphore , DISPATCH_TIME_FOREVER );
3638 while (queue_pending > 0 )
3739 {
40+ main_async_t async ;
3841 queue_position = (queue_position + queue_length - 1 ) % queue_length ;
3942 -- queue_pending ;
40- async_queue [queue_position ].cb (async_queue [queue_position ].context );
43+ async = async_queue [queue_position ];
44+ dispatch_semaphore_signal (async_queue_semaphore );
45+ // call the async block outside the lock
46+ async .cb (async .context );
47+ // continue the lock so we can get correct queue_pending
48+ dispatch_semaphore_wait (async_queue_semaphore , DISPATCH_TIME_FOREVER );
4149 }
4250 dispatch_semaphore_signal (async_queue_semaphore );
4351}
@@ -46,7 +54,7 @@ void main_async_init(void)
4654{
4755 async_queue_semaphore = dispatch_semaphore_create (1 );
4856 async_queue = (main_async_t * )malloc (sizeof (main_async_t ) * queue_length );
49- ev_async_init (& main_async , main_async_dispatch );
57+ ev_async_init (& main_async , main_async_drain );
5058}
5159
5260void main_async_start (EV_P )
0 commit comments