//
//  MYCoroutine.h
//  Coroutines for Mac OS X
//
//  Created by Jens Alfke on 4/29/08.
//  Copyright 2008 Jens Alfke. All rights reserved.
//

#import <Foundation/Foundation.h>


/** Objective-C coroutine class.
    See: http://en.wikipedia.org/wiki/Coroutine 
*/
@interface MYCoroutine : NSObject
{
    @private
    struct CoroX *_coro;
    NSInvocation *_invocation;
    NSString *_name;
}

/** The "main" coroutine: the one corresponding to the execution context before the
    first coroutine is started. */
+ (MYCoroutine*) mainCoroutine;

/** The currently active coroutine. */
+ (MYCoroutine*) currentCoroutine;

/** Creates a new coroutine and starts it, performing the given invocation on it.
    That method must not return! */
+ (MYCoroutine*) startWithInvocation: (NSInvocation*)invocation;

/** Creates but does not start a coroutine. */
- (id) init;


@property (retain) NSInvocation *invocation;

/** The stack size of the coroutine. You can only change this before calling -start! */
@property size_t stackSize;

/** The coroutine's name. You can put anything you want here, as a debugging aid. */
@property (copy) NSString* name;


/** The "main" method that will be called if the coroutine is started with -start.
    The default implementation is empty, so a subclass using -start must override this. */
- (void) main;


/** Returns control to a coroutine.
    The most recent -resume call made from within that coroutine will return.
    The current coroutine will block (i.e. this call won't return)
    until some other coroutine tells it to resume. */
- (void) resume;

- (id) call;

+ (void) yieldToCaller: (id)value;


/** Returns YES if this is the currently executing coroutine. */
@property (readonly) BOOL isCurrent;

/** The number of bytes of stack space left on this coroutine. */
@property (readonly) size_t bytesLeftOnStack;

/** Returns YES if this coroutine is almost out of stack space (less than 8k left) */
@property (readonly) BOOL stackSpaceAlmostGone;


+ (void) setDefaultStackSize: (size_t)stackSize;

@end

