
#import <Foundation/Foundation.h>

#include <dispatch/dispatch.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>

#define REPRODUCE_CASE 1

int32_t final = 32;
volatile unsigned char /* int32_t */ canary1 = 77, count = 0, canary2 = 88;

@interface MYOperation : NSOperation
{
}
@end

@implementation MYOperation

- (id) init
{
	return self;
}

- (void)main
{
	printf("main\n");
}

@end


int
main(int argc, char *argv[])
{
    int i;
    if (argc > 1)
        final = atoi(argv[1]);


/*    __block int32_t count = 0;*/

    for (i = 0; i < final; ++i) {
		char* name;
		asprintf(&name, "test.%d", i);

		dispatch_queue_t queue = dispatch_queue_create(name, NULL);
		free(name);
		dispatch_set_target_queue(queue, dispatch_get_global_queue(0,
                    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)));

        /* async queue */
		dispatch_async(queue, ^{
#if REPRODUCE_CASE
            @autoreleasepool {
                NSString *str = [NSString stringWithUTF8String:"TEST"];
	            NSOperationQueue *ns_queue = [[NSOperationQueue alloc] init];

                MYOperation *operation = [[MYOperation alloc] init];

                [ns_queue addOperation:operation];
                /* ... */
            };
#endif /* REPRODUCE_CASE */
            count = __sync_add_and_fetch(&count, 1);
            printf("after %d count addr %p, value %d\n", (unsigned int)pthread_self(), &count, count);
            fflush(stdout);
            printf("canary1 %d, canary2 %d\n", canary1, canary2);
            fflush(stdout);

            if (count == final) {
                printf("success\n");
                sleep(2);
                exit(0);
            }
        });
	}

	dispatch_main();

	return 0;
}
