1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Actors.xcodeproj/project.pbxproj Tue Apr 29 17:05:32 2008 -0700
1.3 @@ -0,0 +1,235 @@
1.4 +// !$*UTF8*$!
1.5 +{
1.6 + archiveVersion = 1;
1.7 + classes = {
1.8 + };
1.9 + objectVersion = 45;
1.10 + objects = {
1.11 +
1.12 +/* Begin PBXBuildFile section */
1.13 + 2703CFE40DC796DC00DD026B /* MYCoroutine.m in Sources */ = {isa = PBXBuildFile; fileRef = 2703CFE30DC796DC00DD026B /* MYCoroutine.m */; };
1.14 + 2703D1BE0DC7DAD100DD026B /* CoroX.c in Sources */ = {isa = PBXBuildFile; fileRef = 2703D1BD0DC7DAD100DD026B /* CoroX.c */; };
1.15 + 2703D28B0DC7EC5A00DD026B /* MYCoroutineTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2703D28A0DC7EC5A00DD026B /* MYCoroutineTest.m */; };
1.16 + 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
1.17 +/* End PBXBuildFile section */
1.18 +
1.19 +/* Begin PBXCopyFilesBuildPhase section */
1.20 + 8DD76F9E0486AA7600D96B5E /* CopyFiles */ = {
1.21 + isa = PBXCopyFilesBuildPhase;
1.22 + buildActionMask = 8;
1.23 + dstPath = /usr/share/man/man1/;
1.24 + dstSubfolderSpec = 0;
1.25 + files = (
1.26 + );
1.27 + runOnlyForDeploymentPostprocessing = 1;
1.28 + };
1.29 +/* End PBXCopyFilesBuildPhase section */
1.30 +
1.31 +/* Begin PBXFileReference section */
1.32 + 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
1.33 + 2703CFE20DC796DC00DD026B /* MYCoroutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYCoroutine.h; sourceTree = "<group>"; };
1.34 + 2703CFE30DC796DC00DD026B /* MYCoroutine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCoroutine.m; sourceTree = "<group>"; };
1.35 + 2703D1BC0DC7DAD100DD026B /* CoroX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoroX.h; sourceTree = "<group>"; };
1.36 + 2703D1BD0DC7DAD100DD026B /* CoroX.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CoroX.c; sourceTree = "<group>"; };
1.37 + 2703D28A0DC7EC5A00DD026B /* MYCoroutineTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYCoroutineTest.m; sourceTree = "<group>"; };
1.38 + 8DD76FA10486AA7600D96B5E /* Coroutines */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Coroutines; sourceTree = BUILT_PRODUCTS_DIR; };
1.39 +/* End PBXFileReference section */
1.40 +
1.41 +/* Begin PBXFrameworksBuildPhase section */
1.42 + 8DD76F9B0486AA7600D96B5E /* Frameworks */ = {
1.43 + isa = PBXFrameworksBuildPhase;
1.44 + buildActionMask = 2147483647;
1.45 + files = (
1.46 + 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */,
1.47 + );
1.48 + runOnlyForDeploymentPostprocessing = 0;
1.49 + };
1.50 +/* End PBXFrameworksBuildPhase section */
1.51 +
1.52 +/* Begin PBXGroup section */
1.53 + 08FB7794FE84155DC02AAC07 /* Coroutines */ = {
1.54 + isa = PBXGroup;
1.55 + children = (
1.56 + 08FB7795FE84155DC02AAC07 /* Source */,
1.57 + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
1.58 + 1AB674ADFE9D54B511CA2CBB /* Products */,
1.59 + );
1.60 + name = Coroutines;
1.61 + sourceTree = "<group>";
1.62 + };
1.63 + 08FB7795FE84155DC02AAC07 /* Source */ = {
1.64 + isa = PBXGroup;
1.65 + children = (
1.66 + 2703D2A30DC7EE7100DD026B /* Coroutines */,
1.67 + );
1.68 + name = Source;
1.69 + sourceTree = "<group>";
1.70 + };
1.71 + 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
1.72 + isa = PBXGroup;
1.73 + children = (
1.74 + 08FB779EFE84155DC02AAC07 /* Foundation.framework */,
1.75 + );
1.76 + name = "External Frameworks and Libraries";
1.77 + sourceTree = "<group>";
1.78 + };
1.79 + 1AB674ADFE9D54B511CA2CBB /* Products */ = {
1.80 + isa = PBXGroup;
1.81 + children = (
1.82 + 8DD76FA10486AA7600D96B5E /* Coroutines */,
1.83 + );
1.84 + name = Products;
1.85 + sourceTree = "<group>";
1.86 + };
1.87 + 2703D2A30DC7EE7100DD026B /* Coroutines */ = {
1.88 + isa = PBXGroup;
1.89 + children = (
1.90 + 2703CFE20DC796DC00DD026B /* MYCoroutine.h */,
1.91 + 2703CFE30DC796DC00DD026B /* MYCoroutine.m */,
1.92 + 2703D28A0DC7EC5A00DD026B /* MYCoroutineTest.m */,
1.93 + 2703D1BC0DC7DAD100DD026B /* CoroX.h */,
1.94 + 2703D1BD0DC7DAD100DD026B /* CoroX.c */,
1.95 + );
1.96 + path = Coroutines;
1.97 + sourceTree = "<group>";
1.98 + };
1.99 +/* End PBXGroup section */
1.100 +
1.101 +/* Begin PBXNativeTarget section */
1.102 + 8DD76F960486AA7600D96B5E /* Coroutines */ = {
1.103 + isa = PBXNativeTarget;
1.104 + buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "Coroutines" */;
1.105 + buildPhases = (
1.106 + 8DD76F990486AA7600D96B5E /* Sources */,
1.107 + 8DD76F9B0486AA7600D96B5E /* Frameworks */,
1.108 + 8DD76F9E0486AA7600D96B5E /* CopyFiles */,
1.109 + );
1.110 + buildRules = (
1.111 + );
1.112 + dependencies = (
1.113 + );
1.114 + name = Coroutines;
1.115 + productInstallPath = "$(HOME)/bin";
1.116 + productName = Coroutines;
1.117 + productReference = 8DD76FA10486AA7600D96B5E /* Coroutines */;
1.118 + productType = "com.apple.product-type.tool";
1.119 + };
1.120 +/* End PBXNativeTarget section */
1.121 +
1.122 +/* Begin PBXProject section */
1.123 + 08FB7793FE84155DC02AAC07 /* Project object */ = {
1.124 + isa = PBXProject;
1.125 + buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "Actors" */;
1.126 + compatibilityVersion = "Xcode 3.1";
1.127 + hasScannedForEncodings = 1;
1.128 + mainGroup = 08FB7794FE84155DC02AAC07 /* Coroutines */;
1.129 + projectDirPath = "";
1.130 + projectRoot = "";
1.131 + targets = (
1.132 + 8DD76F960486AA7600D96B5E /* Coroutines */,
1.133 + );
1.134 + };
1.135 +/* End PBXProject section */
1.136 +
1.137 +/* Begin PBXSourcesBuildPhase section */
1.138 + 8DD76F990486AA7600D96B5E /* Sources */ = {
1.139 + isa = PBXSourcesBuildPhase;
1.140 + buildActionMask = 2147483647;
1.141 + files = (
1.142 + 2703CFE40DC796DC00DD026B /* MYCoroutine.m in Sources */,
1.143 + 2703D1BE0DC7DAD100DD026B /* CoroX.c in Sources */,
1.144 + 2703D28B0DC7EC5A00DD026B /* MYCoroutineTest.m in Sources */,
1.145 + );
1.146 + runOnlyForDeploymentPostprocessing = 0;
1.147 + };
1.148 +/* End PBXSourcesBuildPhase section */
1.149 +
1.150 +/* Begin XCBuildConfiguration section */
1.151 + 1DEB927508733DD40010E9CD /* Debug */ = {
1.152 + isa = XCBuildConfiguration;
1.153 + buildSettings = {
1.154 + ALWAYS_SEARCH_USER_PATHS = NO;
1.155 + COPY_PHASE_STRIP = NO;
1.156 + GCC_C_LANGUAGE_STANDARD = gnu99;
1.157 + GCC_DYNAMIC_NO_PIC = NO;
1.158 + GCC_ENABLE_FIX_AND_CONTINUE = YES;
1.159 + GCC_MODEL_TUNING = G5;
1.160 + GCC_OPTIMIZATION_LEVEL = 0;
1.161 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
1.162 + GCC_PREFIX_HEADER = "";
1.163 + GCC_TREAT_WARNINGS_AS_ERRORS = YES;
1.164 + INSTALL_PATH = /usr/local/bin;
1.165 + PRODUCT_NAME = Coroutines;
1.166 + WARNING_CFLAGS = "-Wall";
1.167 + };
1.168 + name = Debug;
1.169 + };
1.170 + 1DEB927608733DD40010E9CD /* Release */ = {
1.171 + isa = XCBuildConfiguration;
1.172 + buildSettings = {
1.173 + ALWAYS_SEARCH_USER_PATHS = NO;
1.174 + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
1.175 + GCC_C_LANGUAGE_STANDARD = gnu99;
1.176 + GCC_MODEL_TUNING = G5;
1.177 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
1.178 + GCC_PREFIX_HEADER = "";
1.179 + GCC_TREAT_WARNINGS_AS_ERRORS = YES;
1.180 + INSTALL_PATH = /usr/local/bin;
1.181 + PRODUCT_NAME = Coroutines;
1.182 + WARNING_CFLAGS = "-Wall";
1.183 + };
1.184 + name = Release;
1.185 + };
1.186 + 1DEB927908733DD40010E9CD /* Debug */ = {
1.187 + isa = XCBuildConfiguration;
1.188 + buildSettings = {
1.189 + ALWAYS_SEARCH_USER_PATHS = NO;
1.190 + ARCHS = "$(ARCHS_STANDARD_32_BIT)";
1.191 + GCC_C_LANGUAGE_STANDARD = c99;
1.192 + GCC_OPTIMIZATION_LEVEL = 0;
1.193 + GCC_WARN_ABOUT_RETURN_TYPE = YES;
1.194 + GCC_WARN_UNUSED_VARIABLE = YES;
1.195 + ONLY_ACTIVE_ARCH = YES;
1.196 + PREBINDING = NO;
1.197 + SDKROOT = macosx10.5;
1.198 + };
1.199 + name = Debug;
1.200 + };
1.201 + 1DEB927A08733DD40010E9CD /* Release */ = {
1.202 + isa = XCBuildConfiguration;
1.203 + buildSettings = {
1.204 + ALWAYS_SEARCH_USER_PATHS = NO;
1.205 + ARCHS = "$(ARCHS_STANDARD_32_BIT)";
1.206 + GCC_C_LANGUAGE_STANDARD = c99;
1.207 + GCC_WARN_ABOUT_RETURN_TYPE = YES;
1.208 + GCC_WARN_UNUSED_VARIABLE = YES;
1.209 + PREBINDING = NO;
1.210 + SDKROOT = macosx10.5;
1.211 + };
1.212 + name = Release;
1.213 + };
1.214 +/* End XCBuildConfiguration section */
1.215 +
1.216 +/* Begin XCConfigurationList section */
1.217 + 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "Coroutines" */ = {
1.218 + isa = XCConfigurationList;
1.219 + buildConfigurations = (
1.220 + 1DEB927508733DD40010E9CD /* Debug */,
1.221 + 1DEB927608733DD40010E9CD /* Release */,
1.222 + );
1.223 + defaultConfigurationIsVisible = 0;
1.224 + defaultConfigurationName = Release;
1.225 + };
1.226 + 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "Actors" */ = {
1.227 + isa = XCConfigurationList;
1.228 + buildConfigurations = (
1.229 + 1DEB927908733DD40010E9CD /* Debug */,
1.230 + 1DEB927A08733DD40010E9CD /* Release */,
1.231 + );
1.232 + defaultConfigurationIsVisible = 0;
1.233 + defaultConfigurationName = Release;
1.234 + };
1.235 +/* End XCConfigurationList section */
1.236 + };
1.237 + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
1.238 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/Coroutines/CoroX.c Tue Apr 29 17:05:32 2008 -0700
2.3 @@ -0,0 +1,188 @@
2.4 +/*
2.5 + * CoroX.c
2.6 + * Coroutines for Mac OS X
2.7 + *
2.8 + * Created by Jens Alfke on 4/29/08.
2.9 + * Adapted from Steve Dekorte's libCoroutine:
2.10 + * <http://www.dekorte.com/projects/opensource/libCoroutine/>
2.11 + * by putting it on a piece of wood and banging a few nails through it.
2.12 + * No, actually I removed all the stuff for cross-platform support, leaving only the simple
2.13 + * code that works on Mac OS X 10.5, and then cleaned things up a bit.
2.14 + *
2.15 + * Copyright 2008 Jens Alfke. All rights reserved.
2.16 + * Copyright (c) 2002, 2003 Steve Dekorte. All rights reserved.
2.17 + * License is at the bottom of this file.
2.18 + *
2.19 + */
2.20 +
2.21 +#include "CoroX.h"
2.22 +#include <ucontext.h>
2.23 +#include <stddef.h>
2.24 +#include <stdio.h>
2.25 +#include <assert.h>
2.26 +
2.27 +
2.28 +#define CORO_DEFAULT_STACK_SIZE (65536*4)
2.29 +#define CORO_STACK_SIZE_MIN 8192
2.30 +
2.31 +
2.32 +struct Coro
2.33 +{
2.34 + size_t stackSize;
2.35 + void *stack;
2.36 + ucontext_t env;
2.37 + // The following field works around bug(?) in sys/_structs.h. This field should be part of ucontext_t:
2.38 + _STRUCT_MCONTEXT env_registers;
2.39 + unsigned char isMain;
2.40 +};
2.41 +
2.42 +
2.43 +typedef struct CallbackBlock
2.44 +{
2.45 + void *context;
2.46 + CoroStartCallback *func;
2.47 +} CallbackBlock;
2.48 +
2.49 +
2.50 +Coro *Coro_new(void)
2.51 +{
2.52 + Coro *self = (Coro *)calloc(1, sizeof(Coro));
2.53 + self->stackSize = CORO_DEFAULT_STACK_SIZE;
2.54 + self->stack = NULL;
2.55 + return self;
2.56 +}
2.57 +
2.58 +void Coro_free(Coro *self)
2.59 +{
2.60 + if (self->stack)
2.61 + free(self->stack);
2.62 + free(self);
2.63 +}
2.64 +
2.65 +
2.66 +void *Coro_stack(Coro *self)
2.67 +{
2.68 + return self->stack;
2.69 +}
2.70 +
2.71 +size_t Coro_stackSize(Coro *self)
2.72 +{
2.73 + return self->stackSize;
2.74 +}
2.75 +
2.76 +void Coro_setStackSize_(Coro *self, size_t sizeInBytes)
2.77 +{
2.78 + self->stackSize = sizeInBytes;
2.79 +}
2.80 +
2.81 +uint8_t *Coro_CurrentStackPointer(void) __attribute__ ((noinline));
2.82 +
2.83 +uint8_t *Coro_CurrentStackPointer(void)
2.84 +{
2.85 + uint8_t a;
2.86 + uint8_t *b = &a;
2.87 + return b;
2.88 +}
2.89 +
2.90 +size_t Coro_bytesLeftOnStack(Coro *self)
2.91 +{
2.92 + uint8_t dummy;
2.93 + ptrdiff_t p1 = (ptrdiff_t)(&dummy);
2.94 + ptrdiff_t p2 = (ptrdiff_t)Coro_CurrentStackPointer();
2.95 + int stackMovesUp = p2 > p1;
2.96 + ptrdiff_t start = ((ptrdiff_t)self->stack);
2.97 + ptrdiff_t end = start + self->stackSize;
2.98 +
2.99 + if (stackMovesUp)
2.100 + {
2.101 + return end - p1;
2.102 + }
2.103 + else
2.104 + {
2.105 + return p1 - start;
2.106 + }
2.107 +}
2.108 +
2.109 +int Coro_stackSpaceAlmostGone(Coro *self)
2.110 +{
2.111 + return Coro_bytesLeftOnStack(self) < CORO_STACK_SIZE_MIN;
2.112 +}
2.113 +
2.114 +
2.115 +void Coro_initializeMainCoro(Coro *self)
2.116 +{
2.117 + self->isMain = 1;
2.118 +}
2.119 +
2.120 +
2.121 +static void Coro_StartWithArg(CallbackBlock *block)
2.122 +{
2.123 + (block->func)(block->context);
2.124 + fprintf(stderr,"CoroX error: returned from coro start function\n");
2.125 + abort();
2.126 +}
2.127 +
2.128 +typedef void (*makecontext_func)(void);
2.129 +
2.130 +static void Coro_setup(Coro *self, void *arg)
2.131 +{
2.132 + ucontext_t *ucp = (ucontext_t *) &self->env;
2.133 + getcontext(ucp);
2.134 +
2.135 + ucp->uc_stack.ss_sp = Coro_stack(self);
2.136 + ucp->uc_stack.ss_size = Coro_stackSize(self);
2.137 + ucp->uc_stack.ss_flags = 0;
2.138 + ucp->uc_link = NULL;
2.139 +
2.140 + makecontext(ucp, (makecontext_func)Coro_StartWithArg, 1, arg);
2.141 +}
2.142 +
2.143 +
2.144 +void Coro_startCoro_(Coro *self, Coro *other, void *context, CoroStartCallback *callback)
2.145 +{
2.146 + assert(other->stack==NULL);
2.147 + other->stack = calloc(1, other->stackSize + 16);
2.148 +
2.149 + CallbackBlock callbackBlock = {context,callback};
2.150 + Coro_setup(other, &callbackBlock);
2.151 +
2.152 + Coro_switchTo_(self, other);
2.153 +}
2.154 +
2.155 +void Coro_switchTo_(Coro *self, Coro *next)
2.156 +{
2.157 + swapcontext(&self->env, &next->env);
2.158 +}
2.159 +
2.160 +
2.161 +
2.162 +
2.163 +/*
2.164 + (This is a BSD License)
2.165 +
2.166 + Copyright (c) 2002, 2003 Steve Dekorte
2.167 + Copyright (c) 2008 Jens Alfke
2.168 + All rights reserved.
2.169 +
2.170 + Redistribution and use in source and binary forms, with or without modification, are
2.171 + permitted provided that the following conditions are met:
2.172 +
2.173 + • Redistributions of source code must retain the above copyright notice, this list of
2.174 + conditions and the following disclaimer.
2.175 + • Redistributions in binary form must reproduce the above copyright notice, this list
2.176 + of conditions and the following disclaimer in the documentation and/or other materials
2.177 + provided with the distribution.
2.178 + • Neither the name of the author nor the names of other contributors may be used to
2.179 + endorse or promote products derived from this software without specific prior written
2.180 + permission.
2.181 +
2.182 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
2.183 + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2.184 + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2.185 + THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2.186 + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2.187 + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2.188 + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
2.189 + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2.190 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2.191 +*/
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/Coroutines/CoroX.h Tue Apr 29 17:05:32 2008 -0700
3.3 @@ -0,0 +1,58 @@
3.4 +/*
3.5 + * CoroX.c
3.6 + * Coroutines for Mac OS X
3.7 + *
3.8 + * Created by Jens Alfke on 4/29/08.
3.9 + * Adapted from Steve Dekorte's libCoroutine:
3.10 + * <http://www.dekorte.com/projects/opensource/libCoroutine/>
3.11 + * by putting it on a piece of wood and banging a few nails through it.
3.12 + * No, actually I removed all the stuff for cross-platform support, leaving only the simple
3.13 + * code that works on Mac OS X 10.5, and then cleaned things up a bit.
3.14 + *
3.15 + * Copyright 2008 Jens Alfke. All rights reserved.
3.16 + * Copyright (c) 2002, 2003 Steve Dekorte. All rights reserved.
3.17 + * License is at the bottom of CoroX.c.
3.18 + *
3.19 + */
3.20 +
3.21 +#pragma once
3.22 +#include <stdlib.h>
3.23 +#include <stdint.h>
3.24 +
3.25 +/** C coroutine implementation for Mac OS X.
3.26 + Based on, and API-compatible with, Steve Dekorte's libCoroutine.
3.27 + His docs are at http://www.dekorte.com/projects/opensource/libCoroutine/docs/
3.28 +*/
3.29 +
3.30 +#ifdef __cplusplus
3.31 +extern "C" {
3.32 +#endif
3.33 +
3.34 + typedef struct Coro Coro;
3.35 +
3.36 + Coro *Coro_new(void);
3.37 + void Coro_free(Coro *self);
3.38 +
3.39 + // stack
3.40 +
3.41 + void *Coro_stack(Coro *self);
3.42 + size_t Coro_stackSize(Coro *self);
3.43 + void Coro_setStackSize_(Coro *self, size_t sizeInBytes);
3.44 + size_t Coro_bytesLeftOnStack(Coro *self);
3.45 + int Coro_stackSpaceAlmostGone(Coro *self);
3.46 +
3.47 + // initialization
3.48 +
3.49 + void Coro_initializeMainCoro(Coro *self);
3.50 +
3.51 + typedef void (CoroStartCallback)(void *);
3.52 +
3.53 + void Coro_startCoro_(Coro *self, Coro *other, void *context, CoroStartCallback *callback);
3.54 +
3.55 + // context-switch
3.56 +
3.57 + void Coro_switchTo_(Coro *self, Coro *next);
3.58 +
3.59 +#ifdef __cplusplus
3.60 +}
3.61 +#endif
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/Coroutines/MYCoroutine.h Tue Apr 29 17:05:32 2008 -0700
4.3 @@ -0,0 +1,74 @@
4.4 +//
4.5 +// MYCoroutine.h
4.6 +// Coroutines for Mac OS X
4.7 +//
4.8 +// Created by Jens Alfke on 4/29/08.
4.9 +// Copyright 2008 Jens Alfke. All rights reserved.
4.10 +//
4.11 +
4.12 +#import <Foundation/Foundation.h>
4.13 +
4.14 +
4.15 +/** Objective-C coroutine class.
4.16 + See: http://en.wikipedia.org/wiki/Coroutine
4.17 +*/
4.18 +@interface MYCoroutine : NSObject
4.19 +{
4.20 + @private
4.21 + struct Coro *_coro;
4.22 + NSString *_name;
4.23 +}
4.24 +
4.25 +/** The "main" coroutine: the one corresponding to the execution context before the
4.26 + first coroutine is started. */
4.27 ++ (MYCoroutine*) mainCoroutine;
4.28 +
4.29 +/** The currently active coroutine. */
4.30 ++ (MYCoroutine*) currentCoroutine;
4.31 +
4.32 +/** Creates a new coroutine and starts it, performing the given invocation on it.
4.33 + That method must not return! */
4.34 ++ (MYCoroutine*) startWithInvocation: (NSInvocation*)invocation;
4.35 +
4.36 +/** Creates but does not start a coroutine. */
4.37 +- (id) init;
4.38 +
4.39 +/** Starts a new coroutine, and performs the given invocation on it.
4.40 + The current coroutine will block (i.e. this call won't return)
4.41 + until some other coroutine tells it to resume. */
4.42 +- (void) startWithInvocation: (NSInvocation*)invocation;
4.43 +
4.44 +/** Starts a new coroutine, invoking its -main method as its body.
4.45 + Since the default implementation of -main is empty, this only makes sense to call
4.46 + on an instance of a subclass of MYCoroutine that's overridden -main.
4.47 + The current coroutine will block (i.e. this call won't return)
4.48 + until some other coroutine tells it to resume. */
4.49 +- (void) start;
4.50 +
4.51 +/** The "main" method that will be called if the coroutine is started with -start.
4.52 + The default implementation is empty, so a subclass using -start must override this. */
4.53 +- (void) main;
4.54 +
4.55 +/** Returns control to an already-started (but blocked) coroutine.
4.56 + The most recent -resume call made from within that coroutine will return.
4.57 + The current coroutine will block (i.e. this call won't return)
4.58 + until some other coroutine tells it to resume. */
4.59 +- (void) resume;
4.60 +
4.61 +
4.62 +/** The coroutine's name. You can put anything you want here, as a debugging aid. */
4.63 +@property (copy) NSString* name;
4.64 +
4.65 +/** Returns YES if this is the currently executing coroutine. */
4.66 +@property (readonly) BOOL isCurrent;
4.67 +
4.68 +/** The stack size of the coroutine. You can only change this before calling -start! */
4.69 +@property size_t stackSize;
4.70 +
4.71 +/** The number of bytes of stack space left on this coroutine. */
4.72 +@property (readonly) size_t bytesLeftOnStack;
4.73 +
4.74 +/** Returns YES if this coroutine is almost out of stack space (less than 8k left) */
4.75 +@property (readonly) BOOL stackSpaceAlmostGone;
4.76 +
4.77 +@end
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/Coroutines/MYCoroutine.m Tue Apr 29 17:05:32 2008 -0700
5.3 @@ -0,0 +1,173 @@
5.4 +//
5.5 +// MYCoroutine.m
5.6 +// Coroutines
5.7 +//
5.8 +// Created by Jens Alfke on 4/29/08.
5.9 +// Copyright 2008 Jens Alfke. All rights reserved.
5.10 +// License is at the bottom of this file.
5.11 +//
5.12 +
5.13 +#import "MYCoroutine.h"
5.14 +#import "CoroX.h"
5.15 +
5.16 +
5.17 +#ifndef LogTo
5.18 +#define kEnableLog 0 /* 1 enables logging, 0 disables it */
5.19 +#define LogTo(DOMAIN,MSG,...) do{ if(kEnableLog) NSLog(@""#DOMAIN ": " MSG,__VA_ARGS__); }while(0)
5.20 +#endif
5.21 +
5.22 +#ifndef Warn
5.23 +#define Warn(MSG,...) NSLog(@"WARNING: " #MSG,__VA_ARGS__)
5.24 +#endif
5.25 +
5.26 +
5.27 +@implementation MYCoroutine
5.28 +
5.29 +
5.30 +static MYCoroutine *sMain, *sCurrent;
5.31 +
5.32 +
5.33 ++ (void) initialize
5.34 +{
5.35 + if( self == [MYCoroutine class] ) {
5.36 + sMain = [[self alloc] init];
5.37 + Coro_initializeMainCoro(sMain->_coro);
5.38 + sMain.name = @"MAIN";
5.39 + sCurrent = sMain;
5.40 + }
5.41 +}
5.42 +
5.43 +
5.44 +- (id) init
5.45 +{
5.46 + self = [super init];
5.47 + if (self != nil) {
5.48 + _coro = Coro_new();
5.49 + LogTo(Coroutine,@"INIT %@ : _coro=%p",self,_coro);
5.50 + }
5.51 + return self;
5.52 +}
5.53 +
5.54 +
5.55 +- (void) dealloc
5.56 +{
5.57 + LogTo(Coroutine,@"DEALLOC %@",self);
5.58 + Coro_free(_coro);
5.59 + [super dealloc];
5.60 +}
5.61 +
5.62 +
5.63 +- (NSString*) description
5.64 +{
5.65 + if( _name )
5.66 + return [NSString stringWithFormat: @"%@[%@]", [self class],_name];
5.67 + else
5.68 + return [NSString stringWithFormat: @"%@[%p]", [self class],self];
5.69 +}
5.70 +
5.71 +
5.72 +@synthesize name=_name;
5.73 +
5.74 +
5.75 ++ (MYCoroutine*) mainCoroutine {return sMain;}
5.76 ++ (MYCoroutine*) currentCoroutine {return sCurrent;}
5.77 +
5.78 +- (BOOL) isCurrent {return self==sCurrent;}
5.79 +
5.80 +- (const void*) stack {return Coro_stack(_coro);}
5.81 +- (size_t) stackSize {return Coro_stackSize(_coro);}
5.82 +- (void) setStackSize: (size_t)size {Coro_setStackSize_(_coro,size);}
5.83 +
5.84 +- (size_t) bytesLeftOnStack {return Coro_bytesLeftOnStack(_coro);}
5.85 +- (BOOL) stackSpaceAlmostGone {return Coro_stackSpaceAlmostGone(_coro);}
5.86 +
5.87 +
5.88 +static void startWithInvocation( void *context )
5.89 +{
5.90 + [(NSInvocation*)context invoke];
5.91 +}
5.92 +
5.93 +static void startWithMain( void *context )
5.94 +{
5.95 + [(MYCoroutine*)context main];
5.96 +}
5.97 +
5.98 +- (void) startWithInvocation: (NSInvocation*)invocation
5.99 +{
5.100 + LogTo(Coroutine,@"Starting %@ (currently in %@)",self,sCurrent);
5.101 + MYCoroutine *current = sCurrent;
5.102 + sCurrent = self;
5.103 +
5.104 + if( invocation )
5.105 + Coro_startCoro_(current->_coro, _coro, invocation, &startWithInvocation);
5.106 + else
5.107 + Coro_startCoro_(current->_coro, _coro, self, &startWithMain);
5.108 +
5.109 + sCurrent = current;
5.110 + LogTo(Coroutine,@"...resumed %@ after starting %@",sCurrent,self);
5.111 +}
5.112 +
5.113 +- (void) start
5.114 +{
5.115 + [self startWithInvocation: nil];
5.116 +}
5.117 +
5.118 +
5.119 ++ (MYCoroutine*) startWithInvocation: (NSInvocation*)invocation
5.120 +{
5.121 + MYCoroutine *cr = [[self alloc] init];
5.122 + [cr startWithInvocation: invocation];
5.123 + return cr;
5.124 +}
5.125 +
5.126 +
5.127 +- (void) resume
5.128 +{
5.129 + LogTo(Coroutine,@"Resuming %@ (currently in %@)",self,sCurrent);
5.130 + MYCoroutine *current = sCurrent;
5.131 + sCurrent = self;
5.132 + Coro_switchTo_(current->_coro,_coro);
5.133 + sCurrent = current;
5.134 + LogTo(Coroutine,@"...resumed %@",sCurrent);
5.135 +}
5.136 +
5.137 +
5.138 +- (void) main
5.139 +{
5.140 + // subclasses should override this.
5.141 +}
5.142 +
5.143 +
5.144 +@end
5.145 +
5.146 +
5.147 +
5.148 +
5.149 +/*
5.150 + (This is a BSD License)
5.151 +
5.152 + Copyright (c) 2008 Jens Alfke
5.153 + All rights reserved.
5.154 +
5.155 + Redistribution and use in source and binary forms, with or without modification, are
5.156 + permitted provided that the following conditions are met:
5.157 +
5.158 + • Redistributions of source code must retain the above copyright notice, this list of
5.159 + conditions and the following disclaimer.
5.160 + • Redistributions in binary form must reproduce the above copyright notice, this list
5.161 + of conditions and the following disclaimer in the documentation and/or other materials
5.162 + provided with the distribution.
5.163 + • Neither the name of the author nor the names of other contributors may be used to
5.164 + endorse or promote products derived from this software without specific prior written
5.165 + permission.
5.166 +
5.167 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
5.168 + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5.169 + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
5.170 + THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5.171 + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5.172 + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5.173 + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
5.174 + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5.175 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5.176 +*/
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/Coroutines/MYCoroutineTest.m Tue Apr 29 17:05:32 2008 -0700
6.3 @@ -0,0 +1,88 @@
6.4 +//
6.5 +// MYCoroutineTest.m
6.6 +// Coroutines
6.7 +//
6.8 +// Created by Jens Alfke on 4/29/08.
6.9 +// Copyright 2008 __MyCompanyName__. All rights reserved.
6.10 +//
6.11 +
6.12 +#import "MYCoroutine.h"
6.13 +
6.14 +
6.15 +@interface CoroTest1 : MYCoroutine
6.16 +{
6.17 + int value;
6.18 +}
6.19 +@property int value;
6.20 +@end
6.21 +
6.22 +@interface CoroTest2 : CoroTest1
6.23 +@end
6.24 +
6.25 +
6.26 +CoroTest1 *firstCoro, *secondCoro;
6.27 +
6.28 +
6.29 +@implementation CoroTest2
6.30 +
6.31 +- (void) main
6.32 +{
6.33 + int num = 0;
6.34 +
6.35 + NSLog(@"secondTask created with value %d", self.value);
6.36 +
6.37 + while (1)
6.38 + {
6.39 + NSLog(@"secondTask: %d %d", self.bytesLeftOnStack, num++);
6.40 + [firstCoro resume];
6.41 + }
6.42 +}
6.43 +
6.44 +@end
6.45 +
6.46 +
6.47 +@implementation CoroTest1
6.48 +
6.49 +@synthesize value;
6.50 +
6.51 +- (void) main
6.52 +{
6.53 + int num = 0;
6.54 +
6.55 + NSLog(@"firstTask created with value %d", self.value);
6.56 + secondCoro = [[CoroTest2 alloc] init];
6.57 + secondCoro.name = @"second";
6.58 + secondCoro.value = 2;
6.59 + [secondCoro start];
6.60 +
6.61 + while ( num < 100 )
6.62 + {
6.63 + NSLog(@"firstTask: %d %d", self.bytesLeftOnStack, num++);
6.64 + [secondCoro resume];
6.65 + }
6.66 +
6.67 + [secondCoro release];
6.68 +
6.69 + [[MYCoroutine mainCoroutine] resume];
6.70 +}
6.71 +
6.72 +@end
6.73 +
6.74 +
6.75 +int main()
6.76 +{
6.77 + NSAutoreleasePool *pool = [NSAutoreleasePool new];
6.78 +
6.79 + NSLog(@"Starting test...");
6.80 + //[[[NSThread alloc] init] start];
6.81 + firstCoro = [[CoroTest1 alloc] init];
6.82 + firstCoro.name = @"first";
6.83 + firstCoro.value = 1;
6.84 + [firstCoro start];
6.85 +
6.86 + NSLog(@"Returned from coroutines; exiting");
6.87 +
6.88 + [firstCoro release];
6.89 +
6.90 + [pool drain];
6.91 +}