using System; using System.Collections; using System.Collections.Generic; namespace DepthFirstScheduler { public enum ExecutionStatus { Unknown, Done, Continue, // coroutine or schedulable Error, } public interface IFunctor { T GetResult(); Exception GetError(); ExecutionStatus Execute(); } #region Functor public class Functor : IFunctor { T m_result; public T GetResult() { return m_result; } Exception m_error; public Exception GetError() { return m_error; } Action m_pred; public Functor(Func func) { m_pred = () => m_result = func(); } public ExecutionStatus Execute() { try { m_pred(); return ExecutionStatus.Done; } catch (Exception ex) { m_error = ex; return ExecutionStatus.Error; } } } public static class Functor { /// /// 引数の型を隠蔽した実行器を生成する /// /// 引数の型 /// 結果の型 /// /// /// public static Functor Create(Func arg, Func pred) { return new Functor(() => pred(arg())); } } #endregion #region CoroutineFunctor public class CoroutineFunctor : IFunctor { T m_result; public T GetResult() { return m_result; } Exception m_error; public Exception GetError() { return m_error; } Func m_arg; Func m_starter; Stack m_it; public CoroutineFunctor(Func arg, Func starter) { m_arg = arg; m_starter = starter; } public ExecutionStatus Execute() { if (m_it == null) { m_result = m_arg(); m_it = new Stack(); m_it.Push(m_starter(m_result)); } try { if (m_it.Count!=0) { if (m_it.Peek().MoveNext()) { var nested = m_it.Peek().Current as IEnumerator; if (nested!=null) { m_it.Push(nested); } } else { m_it.Pop(); } return ExecutionStatus.Continue; } else { return ExecutionStatus.Done; } } catch(Exception ex) { m_error = ex; return ExecutionStatus.Error; } } } public static class CoroutineFunctor { public static CoroutineFunctor Create(Func arg, Func starter) { return new CoroutineFunctor(arg, starter); } } #endregion /* public class SchedulableFunctor : IFunctor { Schedulable m_schedulable; Func> m_starter; TaskChain m_chain; public SchedulableFunctor(Func> starter) { m_starter = starter; } public ExecutionStatus Execute() { if (m_chain == null) { m_schedulable = m_starter(); m_chain = TaskChain.Schedule(m_schedulable, ex => m_error = ex); } return m_chain.Next(); } Exception m_error; public Exception GetError() { return m_error; } public T GetResult() { return m_schedulable.Func.GetResult(); } } public static class SchedulableFunctor { public static SchedulableFunctor Create(Func> starter) { return new SchedulableFunctor(starter); } } */ }