//
//  GSAsyncAwait.h
//  GlyphsCore
//
//  Created by Martin Winter on 21/11/2019.
//  Copyright © 2019 schriftgestaltung.de. All rights reserved.
//

#ifndef GSAsyncAwait_h
#define GSAsyncAwait_h

/// Set up before the asynchronous call. The call will be executed on the current thread but will not block if the current thread is the main thread.
#define GS_ASYNC                                             \
	BOOL gs_isMainThread = [NSThread isMainThread];          \
	__block BOOL gs_taskDidFinish = NO;                      \
	dispatch_semaphore_t gs_waitForCompletion;               \
	if (!gs_isMainThread) {                                  \
		gs_waitForCompletion = dispatch_semaphore_create(0); \
	}

/// Call when returning from the asynchronous call; this can be done in multiple locations (e. g. early return).
#define GS_RESOLVE                                       \
	if (gs_isMainThread) {                               \
		gs_taskDidFinish = YES;                          \
	}                                                    \
	else {                                               \
		dispatch_semaphore_signal(gs_waitForCompletion); \
	}

/// Wait for the asynchronous call to finish.
#define GS_AWAIT                                                                                        \
	if (gs_isMainThread) {                                                                              \
		while (!gs_taskDidFinish) {                                                                     \
			__unused NSDate *date = [[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode]; \
		}                                                                                               \
	}                                                                                                   \
	else {                                                                                              \
		dispatch_semaphore_wait(gs_waitForCompletion, DISPATCH_TIME_FOREVER);                           \
	}

#endif /* GSAsyncAwait_h */
