OpenSesame示例源码
using System; using System.Collections.Generic; using System.Threading; namespace OpenSesame { public delegate void BookmarkLocation(Bookmark resumed); [Serializable] public class Bookmark { public Bookmark(string name, BookmarkLocation continueAt) { Name = name; ContinueAt = continueAt; } public string Name { get; set; } public BookmarkLocation ContinueAt { get; set; } public object Payload { get; set; } public BookmarkManager BookmarkManager { get; set; } } public class BookmarkManager { private List<Bookmark> bookmarkList; private ProgramStatement currentProgramStatement; public BookmarkManager() { bookmarkList = new List<Bookmark>(); } public void Add(Bookmark bookmark) { bookmarkList.Add(bookmark); bookmark.BookmarkManager = this; } public void Remove(Bookmark bookmark) { bookmarkList.Remove(bookmark); } public void Resume(string bookmarkName, object payload) { foreach (Bookmark bookmark in bookmarkList) { if (bookmark.Name == bookmarkName) { bookmark.Payload = payload; bookmark.ContinueAt(bookmark); break; } } } // Request execution of a program statement, using an // implicit bookmark that will be resumed when that // program statement completes its execution public void RunProgramStatement(ProgramStatement statement, BookmarkLocation continueAt) { currentProgramStatement = statement; Bookmark bookmark = new Bookmark(statement.GetType().FullName, continueAt); Add(bookmark); statement.Run(this); } // Indicate that the current program statement is done, // so that internally managed bookmarks can be resumed public void Done(bool bAllDone) { if (!bAllDone) Resume(currentProgramStatement.GetType().FullName, currentProgramStatement); else bookmarkList.Clear(); } } [Serializable] public abstract class ProgramStatement { public abstract void Run(BookmarkManager mgr); } public class MythicalRuntime { Dictionary<ProgramHandle, ProgramStatement> ht; private BookmarkManager mgr = new BookmarkManager(); public MythicalRuntime() { ht = new Dictionary<ProgramHandle, ProgramStatement>(); } public BookmarkManager Mgr { get { return mgr; } set { mgr = value; } } public ProgramHandle RunProgram(ProgramStatement program) { //这个新的Guid根据规则创建,而不是简单的new Guid(),以下仅为模拟方法 Guid programId = new Guid(); ProgramHandle programHandle = new ProgramHandle(); programHandle.ProgramId = programId; ht.Add(programHandle, program); //Bookmark的上半部分,用新的thread执行 ThreadPool.QueueUserWorkItem(state => program.Run(state as BookmarkManager), Mgr); return programHandle; } public ProgramHandle GetProgramHandle(Guid programId) { //根据programId恢复已经钝化的程序,假设恢复为read方法 ProgramStatement program = new Read(); //重新构建ProgramHandle ProgramHandle programHandle = new ProgramHandle(); programHandle.ProgramId = programId; //重新加载到内存 ht.Add(programHandle, program); return programHandle; } public void Shutdown() { //从内存中取出所有ProgramHandle, 依次钝化 foreach (ProgramHandle tmpProgramHandle in ht.Keys) { ProgramStatement program = ht[tmpProgramHandle]; tmpProgramHandle.Passivate(program); } ht = null; } } public class ProgramHandle { private Guid programId; public Guid ProgramId { get { return programId; } set { programId = value; } } public void Passivate(ProgramStatement program) { //将program根据关键字programId进行钝化 } public void Resume(string bookmarkName, object payload) { BookmarkManager mgr = new BookmarkManager(); mgr.Resume(bookmarkName, payload); } } [Serializable] public class Read : ProgramStatement { private string text; public string Text { get { return text; } } public override void Run(BookmarkManager mgr) { mgr.Add(new Bookmark("read", ContinueAt)); } void ContinueAt(Bookmark resumed) { text = (string)resumed.Payload; BookmarkManager mgr = resumed.BookmarkManager; mgr.Remove(resumed); mgr.Done(false); } } [Serializable] public class PrintKey : ProgramStatement { private string key; public string Key { get { return key; } } public override void Run(BookmarkManager mgr) { // Print the key key = DateTime.Now.Millisecond.ToString(); Console.WriteLine("here is your key: " + key); mgr.Done(false); } } [Serializable] public class PrintGreeting : ProgramStatement { private string key; public string Key { get { return key; } set { key = value; } } private string s; public string Input { get { return s; } set { s = value; } } public override void Run(BookmarkManager mgr) { //没有做特殊处理,key肯定是null. if (string.IsNullOrEmpty(key)) { Console.WriteLine("OKOK"); return; } // Print the greeting if the key is provided if (key.Equals(s)) Console.WriteLine("hello, world"); else { Console.WriteLine("Wrong key!"); } mgr.Done(false); } } [Serializable] public class ProgramStatementBlock : ProgramStatement { int currentIndex; List<ProgramStatement> statements = new List<ProgramStatement>(); public IList<ProgramStatement> Statements { get { return statements; } } public override void Run(BookmarkManager mgr) { currentIndex = 0; // Empty statement block if (statements.Count == 0) mgr.Done(true); else mgr.RunProgramStatement(statements[0], ContinueAt); } public void ContinueAt(Bookmark resumed) { BookmarkManager mgr = resumed.BookmarkManager; // If we've run all the statements, we're done if (++currentIndex == statements.Count) mgr.Done(true); else // Else, run the next statement mgr.RunProgramStatement(statements[currentIndex], ContinueAt); } } public class OpenSesame_v3 { static void Main(string[] args) { ProgramStatementBlock openSesameProgram = new ProgramStatementBlock(); PrintKey printKey = new PrintKey(); Read read = new Read(); PrintGreeting printGreeting = new PrintGreeting(); printGreeting.Key = printKey.Key; printGreeting.Input = read.Text; openSesameProgram.Statements.Add(printKey); openSesameProgram.Statements.Add(read); openSesameProgram.Statements.Add(printGreeting); MythicalRuntime runtime = new MythicalRuntime(); ProgramHandle handle = runtime.RunProgram(openSesameProgram); string s = Console.ReadLine(); //Bookmark的下半部分,用新的thread执行 ThreadPool.QueueUserWorkItem(state => runtime.Mgr.Resume("read", state), s); // keep the main thread running Console.ReadLine(); } } } |