1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/* Support header for conditionally enabling use of libdispatch.
Copyright (C) 2012 Free Software Foundation, Inc.
Written by: Niels Grewe <niels.grewe@halbordnung.de>
Date: March 2012
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GNUstepBase/GSBlocks.h"
#if HAVE_DISPATCH_H
#include <dispatch.h>
#elif HAVE_DISPATCH_DISPATCH_H
#include <dispatch/dispatch.h>
#endif
/*
* If gnustep-base is built with libdispatch support, these macros will expand
* to code for creating and cleaning up after libdispach queues to which blocks
* can be submitted. If libdispatch is not available, setup and teardown will
* be no-ops, and the block will simply be executed on the calling thread.
*/
#if __has_feature(blocks) && (GS_USE_LIBDISPATCH == 1)
/*
* Older versions of libdispatch do not support concurrent queues.
* We define away the attributes in this case.
*/
#ifndef DISPATCH_QUEUE_SERIAL
#define DISPATCH_QUEUE_SERIAL NULL
#endif
#ifndef DISPATCH_QUEUE_CONCURRENT
#define DISPATCH_QUEUE_CONCURRENT NULL
#endif
#define GS_DISPATCH_GET_DEFAULT_CONCURRENT_QUEUE() dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
/**
* This macro creates a dispatch queue using the attributes
*/
#define GS_DISPATCH_QUEUE_CREATE(attr) dispatch_queue_create(NULL, attr)
/**
* Create a dispatch group
*/
#define GS_DISPATCH_GROUP_CREATE() dispatch_group_create()
/**
* Wait for the dispatch group to finish
*/
#define GS_DISPATCH_GROUP_FINISH(group) dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
/**
* Release an dispatch object.
*/
#define GS_DISPATCH_RELEASE(x) dispatch_release(x)
/**
* Allows an arbitrary block to be submitted to the queue (if available) or run
* in place. Since dispatch blocks return nothing and take no arguments, the
* caller can use the before and after arguments to guard calling the block as
* required.
*/
#define GS_DISPATCH_SUBMIT_BLOCK(group, queue, before, after, block, args, ...) \
if (queue != NULL) {\
dispatch_group_async(group, queue, ^(void){before block(args, ## __VA_ARGS__); after});\
} else {\
before\
block(args, ## __VA_ARGS__);\
after\
}
/**
* Submits a block without special provisions.
*/
#define GS_DISPATCH_SUBMIT_BLOCK_NO_ARGS(group, queue, block) dispatch_group_async(group, queue, block)
/**
* Convenience macro to create concurrent dispatch queues for the various
* -enumerateUsingBlock: methods. Non-concurrent will be run in place.
*/
#define GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(queue, opts)\
dispatch_queue_t queue = NULL;\
dispatch_group_t queue ## Group = NULL;\
if (opts & NSEnumerationConcurrent)\
{\
queue = GS_DISPATCH_GET_DEFAULT_CONCURRENT_QUEUE();\
queue ## Group = GS_DISPATCH_GROUP_CREATE();\
}
/**
* Convenience macro to destroy concurrent dispatch queues for the various
* -enumerateUsingBlock: methods.
*/
#define GS_DISPATCH_TEARDOWN_QUEUE_AND_GROUP_FOR_ENUMERATION(queue, opts)\
if (queue != NULL) { \
GS_DISPATCH_GROUP_FINISH(queue ## Group);\
GS_DISPATCH_RELEASE(queue ## Group);\
if (NO == (opts & NSEnumerationConcurrent))\
{\
GS_DISPATCH_RELEASE(queue);\
}\
}
#else
/*
* No-Op defintions if libdispatch is not supposed to be used.
*/
#define DISPATCH_QUEUE_SERIAL 0
#define DISPATCH_QUEUE_CONCURRENT 0
#define dispatch_queue_attr_t int
#define dispatch_queue_t int
#define dispatch_group_t int
#define GS_DISPATCH_GET_DEFAULT_CONCURRENT_QUEUE() 0
#define GS_DISPATCH_QUEUE_CREATE(attr) 0
#define GS_DISPATCH_GROUP_CREATE() 0
#define GS_DISPATCH_GROUP_FINISH(group)
#define GS_DISPATCH_RELEASE(x)
#define GS_DISPATCH_SUBMIT_BLOCK(group, queue, before, after, block, args...) CALL_BLOCK(block, args)
#define GS_DISPATCH_SUBMIT_BLOCK_NO_ARGS(group, queue, block) CALL_BLOCK_NO_ARGS(block)
#define GS_DISPATCH_CREATE_QUEUE_AND_GROUP_FOR_ENUMERATION(queue, opts)
#define GS_DISPATCH_TEARDOWN_QUEUE_AND_GROUP_FOR_ENUMERATION(queue, opts)
#endif
|