Permalink
Browse files

source code to stackless C# blog post

  • Loading branch information...
refractalize committed Feb 18, 2010
1 parent 1fe7fe9 commit 214f7814aefa23557d2f392f30cfbf5990226cc3
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A4615941-EE95-4BA1-8511-A18389B09E51}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Erlang.Tests</RootNamespace>
+ <AssemblyName>Erlang.Tests</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Moq, Version=3.0.204.1, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\References\Moq\Moq.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.5.2.9222, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\References\NUnit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MailBoxTest.cs" />
+ <Compile Include="MergeSorterTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Erlang\Erlang.csproj">
+ <Project>{B0F7CF4E-E9B0-448C-84AE-D2860305AEC5}</Project>
+ <Name>Erlang</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
@@ -0,0 +1,38 @@
+using NUnit.Framework;
+
+namespace Erlang.Tests {
+ [TestFixture]
+ public class MailBoxTest {
+ [Test]
+ public void ShouldReturnMessageWhenOneAvailable() {
+ var mailbox = new MailBox<string>();
+ mailbox.AddMessage("hi");
+
+ string message;
+ Assert.That(mailbox.TryGetNextMessage(out message));
+ Assert.That(message, Is.EqualTo("hi"));
+ }
+
+ [Test]
+ public void ShouldReturnFalseIfNoMessages() {
+ var mailbox = new MailBox<string>();
+
+ string message;
+ Assert.That(mailbox.TryGetNextMessage(out message), Is.False);
+ }
+
+ [Test]
+ public void ShouldReturnMessagesInOrderTheyWereAdded() {
+ var mailbox = new MailBox<string>();
+ mailbox.AddMessage("one");
+ mailbox.AddMessage("two");
+
+ string message;
+ Assert.That(mailbox.TryGetNextMessage(out message));
+ Assert.That(message, Is.EqualTo("one"));
+
+ Assert.That(mailbox.TryGetNextMessage(out message));
+ Assert.That(message, Is.EqualTo("two"));
+ }
+ }
+}
@@ -0,0 +1,21 @@
+using NUnit.Framework;
+
+namespace Erlang.Tests {
+ [TestFixture]
+ public class MergeSorterTest {
+ [Test]
+ public void ShouldMerge2ItemsAscendings() {
+ Assert.That(MergeSorter.Merge(new[] {2}, new[] {1}), Is.EqualTo(new[] {1, 2}));
+ }
+
+ [Test]
+ public void ShouldMergeDifferentSizedArrays() {
+ Assert.That(MergeSorter.Merge(new[] {2}, new[] {1, 3}), Is.EqualTo(new[] {1, 2, 3}));
+ }
+
+ [Test]
+ public void ShouldMergeArraysWithEqualEntries() {
+ Assert.That(MergeSorter.Merge(new[] {1, 3, 5}, new[] {1, 2, 3}), Is.EqualTo(new[] {1, 1, 2, 3, 3, 5}));
+ }
+ }
+}
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Erlang.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("BBC Worldwide")]
+[assembly: AssemblyProduct("Erlang.Tests")]
+[assembly: AssemblyCopyright("Copyright © BBC Worldwide 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a215b123-c5a9-4a8a-a85e-ce4888cb3582")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
View
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Erlang", "Erlang\Erlang.csproj", "{B0F7CF4E-E9B0-448C-84AE-D2860305AEC5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Erlang.Tests", "Erlang.Tests\Erlang.Tests.csproj", "{A4615941-EE95-4BA1-8511-A18389B09E51}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B0F7CF4E-E9B0-448C-84AE-D2860305AEC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0F7CF4E-E9B0-448C-84AE-D2860305AEC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0F7CF4E-E9B0-448C-84AE-D2860305AEC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0F7CF4E-E9B0-448C-84AE-D2860305AEC5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A4615941-EE95-4BA1-8511-A18389B09E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A4615941-EE95-4BA1-8511-A18389B09E51}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A4615941-EE95-4BA1-8511-A18389B09E51}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A4615941-EE95-4BA1-8511-A18389B09E51}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{B0F7CF4E-E9B0-448C-84AE-D2860305AEC5}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Erlang</RootNamespace>
+ <AssemblyName>Erlang</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="IScheduler.cs" />
+ <Compile Include="MailBox.cs" />
+ <Compile Include="MergeSort.cs" />
+ <Compile Include="MergeSorter.cs" />
+ <Compile Include="MergeSortMessage.cs" />
+ <Compile Include="PingPong.cs" />
+ <Compile Include="Process.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Scheduler.cs" />
+ <Compile Include="SpawnLots.cs" />
+ <Compile Include="Yield.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
@@ -0,0 +1,6 @@
+namespace Erlang {
+ public interface IScheduler {
+ int ProcessCount { get; }
+ void Spawn(params IProcess[] processes);
+ }
+}
View
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Erlang {
+ public class MailBox<T> {
+ private Queue<T> Messages;
+
+ public MailBox() {
+ Messages = new Queue<T>();
+ }
+
+ public void AddMessage(T message) {
+ Messages.Enqueue(message);
+ }
+
+ public bool TryGetNextMessage(out T message) {
+ if (Messages.Count > 0) {
+ message = Messages.Dequeue();
+ return true;
+ } else {
+ message = default(T);
+ return false;
+ }
+ }
+ }
+}
View
@@ -0,0 +1,24 @@
+using System;
+
+namespace Erlang {
+ public class MergeSort : Process<MergeSortMessage> {
+ private readonly int[] Items;
+ public int[] Results { get; set; }
+
+ public MergeSort(int[] items) {
+ Items = items;
+ }
+
+ public override Yield Start() {
+ var mergeSorter = new MergeSorter();
+ mergeSorter.Send(new MergeSortMessage {Caller = this, Items = Items});
+
+ Spawn(mergeSorter);
+
+ return Receive(m => {
+ Results = m.Items;
+ return null;
+ });
+ }
+ }
+}
@@ -0,0 +1,6 @@
+namespace Erlang {
+ public class MergeSortMessage {
+ public int[] Items;
+ public Process<MergeSortMessage> Caller;
+ }
+}
@@ -0,0 +1,49 @@
+using System.Linq;
+
+namespace Erlang {
+ public class MergeSorter : Process<MergeSortMessage> {
+ public override Yield Start() {
+ return Receive(qs => {
+ if (qs.Items.Length <= 1) {
+ qs.Caller.Send(new MergeSortMessage { Items = qs.Items });
+ return null;
+ } else {
+ int split = qs.Items.Length / 2;
+ int[] first = qs.Items.Take(split).ToArray();
+ int[] second = qs.Items.Skip(split).ToArray();
+
+ var firstProcess = new MergeSorter();
+ firstProcess.Send(new MergeSortMessage { Caller = this, Items = first });
+ Spawn(firstProcess);
+ var secondProcess = new MergeSorter();
+ secondProcess.Send(new MergeSortMessage { Caller = this, Items = second });
+ Spawn(secondProcess);
+
+ return Receive(result1 => Receive(result2 => {
+ qs.Caller.Send(new MergeSortMessage { Items = Merge(result1.Items, result2.Items) });
+ return null;
+ }));
+ }
+ });
+ }
+
+ internal static int[] Merge(int[] items1, int[] items2) {
+ var merged = new int[items1.Length + items2.Length];
+
+ int i1 = 0, i2 = 0;
+ for (int m = 0; m < merged.Length; m++) {
+ if (items1.Length <= i1) {
+ merged[m] = items2[i2++];
+ } else if (items2.Length <= i2) {
+ merged[m] = items1[i1++];
+ } else if (items1[i1] < items2[i2]) {
+ merged[m] = items1[i1++];
+ } else {
+ merged[m] = items2[i2++];
+ }
+ }
+
+ return merged;
+ }
+ }
+}
Oops, something went wrong.

0 comments on commit 214f781

Please sign in to comment.