diff --git a/src/common/Reference.cpp b/src/common/Reference.cpp index 38e28e099..127023974 100644 --- a/src/common/Reference.cpp +++ b/src/common/Reference.cpp @@ -64,21 +64,31 @@ void Reference::unref() } } -void Reference::push() +void Reference::push(lua_State *newL) { if (idx != LUA_REFNIL) { - luax_insist(L, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME); - lua_rawgeti(L, -1, idx); - lua_remove(L, -2); + luax_insist(newL, LUA_REGISTRYINDEX, REFERENCE_TABLE_NAME); + lua_rawgeti(newL, -1, idx); + lua_remove(newL, -2); } else - lua_pushnil(L); + lua_pushnil(newL); } -lua_State *Reference::getL() +void Reference::push() +{ + push(L); +} + +lua_State *Reference::getL() const { return L; } +void Reference::setL(lua_State *newL) +{ + L = newL; +} + } // love diff --git a/src/common/Reference.h b/src/common/Reference.h index 5d7341b20..eb8e8b288 100644 --- a/src/common/Reference.h +++ b/src/common/Reference.h @@ -63,6 +63,14 @@ public: **/ void unref(); + /** + * Pushes the referred value onto the stack of a different coroutine + * in the same main Lua state. + * THIS SHOULD NOT BE USED FOR DIFFERENT LUA STATES (created with + * luaL_newstate)! Only with different coroutines! + **/ + void push(lua_State *newL); + /** * Pushes the referred value onto the stack. **/ @@ -72,7 +80,15 @@ public: * Gets the Lua state associated with this * reference. **/ - lua_State *getL(); + lua_State *getL() const; + + /** + * Associates a new Lua state with this reference. + * THIS IS DANGEROUS! It is only designed to be + * used with different coroutines from the same + * main Lua state! + **/ + void setL(lua_State *newL); private: diff --git a/src/modules/physics/box2d/Fixture.cpp b/src/modules/physics/box2d/Fixture.cpp index f133bac62..9b80ef222 100644 --- a/src/modules/physics/box2d/Fixture.cpp +++ b/src/modules/physics/box2d/Fixture.cpp @@ -39,10 +39,10 @@ namespace box2d Fixture::Fixture(Body *body, Shape *shape, float density) : body(body) - , fixture(NULL) + , fixture(nullptr) { data = new fixtureudata(); - data->ref = 0; + data->ref = nullptr; b2FixtureDef def; def.shape = shape->shape; def.userData = (void *)data; @@ -65,13 +65,10 @@ Fixture::Fixture(b2Fixture *f) Fixture::~Fixture() { - if (data->ref != 0) + if (data != nullptr) delete data->ref; delete data; - data = NULL; - - fixture = NULL; } Shape::Type Fixture::getType() const @@ -127,14 +124,14 @@ Body *Fixture::getBody() const Shape *Fixture::getShape() const { if (!fixture->GetShape()) - return NULL; + return nullptr; return new Shape(fixture->GetShape(), false); } bool Fixture::isValid() const { - return fixture != 0; + return fixture != nullptr; } void Fixture::setFilterData(int *v) @@ -230,21 +227,24 @@ int Fixture::setUserData(lua_State *L) { love::luax_assert_argc(L, 1, 1); - if (data->ref != 0) + if (data->ref != nullptr) { + // We set the Reference's lua_State to this one before deleting it, so + // it unrefs using the current lua_State's stack. This is necessary + // if setUserData is called in a coroutine. + data->ref->setL(L); delete data->ref; - data->ref = 0; } data->ref = new Reference(L); + return 0; } int Fixture::getUserData(lua_State *L) { - love::luax_assert_argc(L, 0, 0); - if (data->ref != 0) - data->ref->push(); + if (data->ref != nullptr) + data->ref->push(L); else lua_pushnil(L); @@ -311,10 +311,10 @@ void Fixture::destroy(bool implicit) return; } - if (!implicit && fixture != 0) + if (!implicit && fixture != nullptr) body->body->DestroyFixture(fixture); Memoizer::remove(fixture); - fixture = NULL; + fixture = nullptr; // Box2D fixture destroyed. Release its reference to the love Fixture. this->release();