top of page
Search

Canceling a dispatch_queue_t in C Using Context

  • Writer: Kiranbir Sodhia
    Kiranbir Sodhia
  • Aug 12, 2013
  • 2 min read

This is a really dirty method to cancel out a queue in C. Whenever a block is added to a queue, it will retain the queue. The queue won’t truly be released after dispatch_release unless there are no pending blocks. A lot of people will use a weak pointer in C++ and Objective-C, but there isn’t anything similar in C, except maybe using a static variable. Furthermore, you might not want to actually abort and flush out your queue. However, there is an easy hack in case none of these really bother you. It involves making use of dispatch_set_context and dispatch_get_context.

dispatch_queue_t m_dispatch_queue_create( char * label, dispatch_queue_attr_t attr )
{
    dispatch_queue_t q = dispatch_queue_create( label, attr );
    dispatch_set_context( q, (void *) true ); // mark the queue as available
    return q;
}

void m_dispatch_release( dispatch_queue_t q )
{
    // unless the queue is protected, more blocks (upto 1 for serial)
    // can be queued and executed prior to the next operation.
    dispatch_set_context( q, (void*) false );  // mark the queue as unavailable
    dispatch_release( q );
}

void m_dispatch_async( dispatch_queue_t q, dispatch_block_t block )
{
    dispatch_async( q,
    ^{
        bool run = dispatch_get_context( q );
        //  only execute the block if the queue is available
        if ( run )
        {
            block();
        }
        else
        {
            printf( "cancelled\n" );
        }
    } );
}

int main(int argc, char *argv[])
{
    dispatch_queue_t q = m_dispatch_queue_create( "com.apple.test", NULL );
    for( unsigned i = 0; i < 5; i++ )
    {
        m_dispatch_async( q,
        ^{
            printf("executing block %u\n", i );
            sleep(1);
        } );
    }
    sleep(2);
    m_dispatch_release( q );
    sleep(5);
}

Following the code, the output should look something like below. Depending on the timing of your system, the number of blocks that execute might differ.

Output:

executing block 0
executing block 1
cancelled
cancelled
cancelled

It’s a dirty solution, but hey…

 
 
 

Recent Posts

See All

Comments


bottom of page