/*
 * Copyright (c) 2008-2011 Apple Inc. All rights reserved.
 *
 * @APPLE_APACHE_LICENSE_HEADER_START@
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @APPLE_APACHE_LICENSE_HEADER_END@
 */

#include <dispatch/dispatch.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#ifdef __APPLE__
#include <libkern/OSAtomic.h>
#endif
#include <math.h>
#include <bsdtests.h>
#include "dispatch_test.h"

#ifndef NSEC_PER_SEC
#define NSEC_PER_SEC 1000000000
#endif

#if TARGET_OS_EMBEDDED
#define LOOP_COUNT 50000
#else
#define LOOP_COUNT 200000
#endif

static void test_group_notify(void*);

static dispatch_group_t
create_group(size_t count, unsigned int delay)
{
	size_t i;

	dispatch_group_t group = dispatch_group_create();

	for (i = 0; i < count; ++i) {
		dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
		assert(queue);

		dispatch_group_async(group, queue, ^{
			if (delay) {
				fprintf(stderr, "sleeping...\n");
				sleep(delay);
				fprintf(stderr, "done.\n");
			}
		});

		dispatch_release(queue);
		}
	return group;
}

static void
test_group(void *ctxt __attribute__((unused)))
{
	long res;
	dispatch_group_t group;

	group = create_group(100, 0);
	test_ptr_notnull("dispatch_group_async", group);

	dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

	// should be OK to re-use a group
	dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{});
	dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

	dispatch_release(group);
	group = NULL;

	group = create_group(3, 7);
	test_ptr_notnull("dispatch_group_async", group);

	res = dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC));
	test_long("dispatch_group_wait", !res, 0);

	// retry after timeout (this time succeed)
	res = dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC));
	test_long("dispatch_group_wait", res, 0);

	dispatch_release(group);
	group = NULL;

	group = create_group(100, 0);
	test_ptr_notnull("dispatch_group_async", group);

	dispatch_group_notify(group, dispatch_get_main_queue(), ^{
		dispatch_test_current("Notification Received", dispatch_get_main_queue());
		dispatch_async_f(dispatch_get_main_queue(), NULL, test_group_notify);
	});

	dispatch_release(group);
	group = NULL;
}

static long completed;

static void
test_group_notify2(long cycle, dispatch_group_t tested)
{
	static dispatch_queue_t rq, nq;
	static dispatch_once_t once;
	dispatch_once(&once, ^{
		rq = dispatch_queue_create("release", 0);
		dispatch_suspend(rq);
		nq = dispatch_queue_create("notify", 0);
	});
	dispatch_resume(rq);

	// n=4 works great for a 4CPU Mac Pro, this might work for a wider range of
	// systems.
#if HAVE_ARC4RANDOM
	const int n = 1 + arc4random() % 8;
#else
    const int n = 1 + random() % 8;
#endif
	dispatch_group_t group = dispatch_group_create();
	dispatch_queue_t qa[n];

	dispatch_group_enter(group);
	for (int i = 0; i < n; i++) {
		char buf[48];
		sprintf(buf, "T%ld-%d", cycle, i);
		qa[i] = dispatch_queue_create(buf, 0);
	}

	__block float eh = 0;
	for (int i = 0; i < n; i++) {
		dispatch_queue_t q = qa[i];
		dispatch_group_async(group, q, ^{
			// Seems to trigger a little more reliably with some work being
			// done in this block
			assert(cycle && "cycle must be non-zero");
			eh = (float)sin(M_1_PI / cycle);
		});
	}
	dispatch_group_leave(group);

	dispatch_group_notify(group, nq, ^{
		completed = cycle;
		dispatch_group_leave(tested);
	});

	// Releasing qa's queues here seems to avoid the race, so we are arranging
	// for the current iteration's queues to be released on the next iteration.
	dispatch_sync(rq, ^{});
	dispatch_suspend(rq);
	for (int i = 0; i < n; i++) {
		dispatch_queue_t q = qa[i];
		dispatch_async(rq, ^{ dispatch_release(q); });
	}
	dispatch_release(group);
}

static void
test_group_notify(void *ctxt __attribute__((unused)))
{
	// <rdar://problem/11445820>
	dispatch_group_t tested = dispatch_group_create();
	test_ptr_notnull("dispatch_group_create", tested);
	long i;
	for (i = 1; i <= LOOP_COUNT; i++) {
		if (!(i % (LOOP_COUNT/10))) {
			fprintf(stderr, "#%ld\n", i);
		}
		dispatch_group_enter(tested);
		test_group_notify2(i, tested);
		if (dispatch_group_wait(tested, dispatch_time(DISPATCH_TIME_NOW,
				NSEC_PER_SEC))) {
			break;
		}
	}
	test_long("dispatch_group_notify", i - 1, LOOP_COUNT);
	test_stop();
}

int
main(void)
{
	dispatch_test_start("Dispatch Group");
	dispatch_async_f(dispatch_get_main_queue(), NULL, test_group);
	dispatch_main();

	return 0;
}
