#include <iostream>#include <dispatch/dispatch.h>const int count = 50;uint64_t our_results;int do_work(int _i){ printf("Doing Work %d\n", _i); usleep(25000); return _i;}int do_work2(int _i){ printf("Doing Work2 %d\n", _i); usleep(25000); return _i;}void Group_Finalize(void * Variable){ printf("Our Group is now cleaned up\n");}int main (int argc, char * const argv[]) { printf("Starting work\n"); // Our Variables dispatch_queue_t exampleQueue, exampleQueue2; dispatch_group_t Our_Group; // We create a group that we can actually watch Our_Group = dispatch_group_create(); // We create two Queues // These two queues will be ran concurrently // First argument is a label // Second argument isn't used yet exampleQueue = dispatch_queue_create( "com.example.unique.identifier", NULL ); exampleQueue2 = dispatch_queue_create( "com.example.unique.identifier2", NULL ); // Function fails to ever get called! // Should get called when dispatch_release is called on Our_Group dispatch_set_finalizer_f(Our_Group, Group_Finalize); printf("Before ASync\n"); // This function tells the dispatch group that, hey, we will be adding this to the group dispatch_group_async(Our_Group, exampleQueue, ^{ printf("Entering Group\n"); // This increments how many things are in our group dispatch_group_enter(Our_Group); // This is a for loop that could be split up in different threads // Still runs in a FIFO motion though // dispatch_get_global_queue, first argument is the priority // 2 is high, 0 is default, and -2 is low // Dispatch_apply's first argument is how many times you want to go // from 0 to count - 1 // Third argument is just a function call // the ^ allows us to merge a function directly in to it, kinda neat // never knew you could do that // Function is void(^)(size_t) or void(*)(size_t) if I recall dispatch_apply(count, dispatch_get_global_queue(2, 0), ^(size_t i){ // Just calls function do_work and adds result to our_results our_results += do_work(i); }); printf("Done with Our_Work\n");\ // This decrements how many things are in our group // Our group thing count must be at 0 or dispatch_group_wait will never end dispatch_group_leave(Our_Group); }); // Pretty much same as above printf("Before ASync2\n"); // If you change below line to the first queue, they will run in FIFO style motion dispatch_group_async(Our_Group, exampleQueue2, ^{ printf("Entering Group2\n"); dispatch_group_enter(Our_Group); dispatch_apply(count, dispatch_get_global_queue(2, 0), ^(size_t i){ our_results += do_work2(i); }); printf("Done with Our_Work2\n");\ dispatch_group_leave(Our_Group); }); printf("Starting to wait\n"); // dispatch_group_wait does exactly what you would expect // first argument is the group we are waiting on // and second argument is the length of time // DISPATCH_TIME_NOW is also available // returns 0 on everything done // not 0 if everything isn't done or timeout was reached // second argument can also be a length of time // See docs if you want to know how to do if(dispatch_group_wait(Our_Group, DISPATCH_TIME_FOREVER) == 0) { printf("Done Waiting?\n"); } // Release our objects // All creates must have a release dispatch_release( exampleQueue ); dispatch_release( exampleQueue2 ); dispatch_release( Our_Group ); printf("Done Doing work\n"); printf("Result is %lld\n", our_results); return 0;}