Commit 2a934954 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Generators are not reentrant

parent abbbde02
......@@ -61,12 +61,17 @@ Box* generatorSend(Box* s, Box* v) {
assert(s->cls == generator_cls);
BoxedGenerator* self = static_cast<BoxedGenerator*>(s);
if (self->running)
raiseExcHelper(ValueError, "generator already executing");
// check if the generator already exited
if (self->entryExited)
raiseExcHelper(StopIteration, "");
self->returnValue = v;
self->running = true;
swapcontext(&self->returnContext, &self->context);
self->running = false;
// propagate exception to the caller
if (self->exception)
......@@ -130,7 +135,7 @@ extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, B
extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args)
: Box(generator_cls), function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false),
returnValue(nullptr), exception(nullptr) {
running(false), returnValue(nullptr), exception(nullptr) {
giveAttr("__name__", boxString(function->f->source->getName()));
......
......@@ -524,6 +524,7 @@ public:
GCdArray* args;
bool entryExited;
bool running;
Box* returnValue;
Box* exception;
......
# From PEP 255: "A generator cannot be resumed while it is actively running"
def g():
i = me.next()
yield i
me = g()
try:
me.next()
except ValueError, e:
# Should be: "generator already executing"
print e
# Start a generator on one thread, pass it to another, and have that execute it for a while
def gen():
while True:
for i in xrange(100):
......
# Pass a started generator to two different threads, and make them both
# try to run it at the same time.
started = []
def gen():
started.append(None)
while len(started) == 1:
pass
yield "done"
done = []
def run_through(g, i):
if i == 0:
print g.next()
else:
while len(started) < 1:
pass
try:
print g.next()
except ValueError, e:
print e
started.append(None)
done.append(None)
g = gen()
from thread import start_new_thread
start_new_thread(run_through, (g, 0))
start_new_thread(run_through, (g, 1))
import time
while len(done) < 2:
time.sleep(0.01)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment