我想看看这个:http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html,它非常有趣,应该提供一个很好的起点。当然,我们使用 Java,所以我们可以做得更好(或者可能更糟,因为没有宏:))
根据我对协程的理解,你通常有一个producer and a consumer协程(或者至少这是最常见的模式)。但从语义上讲,您不希望生产者调用消费者,反之亦然,因为这会引入不对称性。但考虑到基于堆栈的语言的工作方式,我们需要有人来进行调用。
所以这是一个非常简单的类型层次结构:
public interface CoroutineProducer<T>
{
public T Produce();
public boolean isDone();
}
public interface CoroutineConsumer<T>
{
public void Consume(T t);
}
public class CoroutineManager
{
public static Execute<T>(CoroutineProducer<T> prod, CoroutineConsumer<T> con)
{
while(!prod.IsDone()) // really simple
{
T d = prod.Produce();
con.Consume(d);
}
}
}
当然现在最困难的部分是实施接口,特别是很难将计算分解为单独的步骤。为此,您可能需要一整套持久控制结构。基本思想是我们想要模拟非本地控制转移(最终有点像我们模拟一个goto
)。我们基本上希望不再使用堆栈和pc
(程序计数器)通过将当前操作的状态保存在堆中而不是堆栈中。因此我们需要一堆辅助类。
例如:
假设在理想的世界中,您想要编写一个如下所示的消费者(伪代码):
boolean is_done;
int other_state;
while(!is_done)
{
//read input
//parse input
//yield input to coroutine
//update is_done and other_state;
}
我们需要像这样抽象局部变量is_done
and other_state
我们需要抽象 while 循环本身,因为我们的yield
like 操作不会使用堆栈。因此,让我们创建一个 while 循环抽象和关联的类:
enum WhileState {BREAK, CONTINUE, YIELD}
abstract class WhileLoop<T>
{
private boolean is_done;
public boolean isDone() { return is_done;}
private T rval;
public T getReturnValue() {return rval;}
protected void setReturnValue(T val)
{
rval = val;
}
public T loop()
{
while(true)
{
WhileState state = execute();
if(state == WhileState.YIELD)
return getReturnValue();
else if(state == WhileState.BREAK)
{
is_done = true;
return null;
}
}
}
protected abstract WhileState execute();
}
这里的基本技巧是移动local变量为class变量并将范围块转换为类,这使我们能够在产生返回值后“重新进入”“循环”。
现在来实现我们的生产者
public class SampleProducer : CoroutineProducer<Object>
{
private WhileLoop<Object> loop;//our control structures become state!!
public SampleProducer()
{
loop = new WhileLoop()
{
private int other_state;//our local variables become state of the control structure
protected WhileState execute()
{
//this implements a single iteration of the loop
if(is_done) return WhileState.BREAK;
//read input
//parse input
Object calcluated_value = ...;
//update is_done, figure out if we want to continue
setReturnValue(calculated_value);
return WhileState.YIELD;
}
};
}
public Object Produce()
{
Object val = loop.loop();
return val;
}
public boolean isDone()
{
//we are done when the loop has exited
return loop.isDone();
}
}
类似的技巧可以用于其他基本控制流结构。理想情况下,您可以构建这些帮助程序类的库,然后使用它们来实现这些简单的接口,最终为您提供协同例程的语义。我确信我在这里写的所有内容都可以进行概括和扩展。