Browse Source

Fixed memory leaks in love.physics. When a World is garbage-collected it now implicitly calls World:destroy, which also destroys all Bodies, Fixtures, and Joints that belong to it.

Alex Szpakowski 9 years ago
parent
commit
aca369e5d4

+ 2 - 2
src/modules/physics/box2d/Body.cpp

@@ -59,7 +59,7 @@ Body::Body(b2Body *b)
 	, udata(nullptr)
 {
 	udata = (bodyudata *) b->GetUserData();
-	world.set((World *) Memoizer::find(b->GetWorld()));
+	world = (World *) Memoizer::find(b->GetWorld());
 	// Box2D body holds a reference to the love Body.
 	this->retain();
 	Memoizer::add(body, this);
@@ -420,7 +420,7 @@ bool Body::isFixedRotation() const
 
 World *Body::getWorld() const
 {
-	return world.get();
+	return world;
 }
 
 int Body::getFixtureList(lua_State *L) const

+ 3 - 7
src/modules/physics/box2d/Body.h

@@ -435,13 +435,9 @@ private:
 	 **/
 	int pushVector(lua_State *L, const b2Vec2 &v);
 
-	// We need a shared_ptr to the parent World,
-	// because World can not be destroyed as long as
-	// bodies exists in it.
-	//
-	// This ensures that a World only can be destroyed
-	// once all bodies have been destroyed too.
-	StrongRef<World> world;
+	// FIXME: This should be a weak reference, rather than being completely
+	// unowned?
+	World *world;
 
 	bodyudata *udata;
 

+ 2 - 2
src/modules/physics/box2d/Joint.cpp

@@ -40,7 +40,7 @@ namespace box2d
 {
 
 Joint::Joint(Body *body1)
-	: world(body1->world.get())
+	: world(body1->world)
 	, udata(nullptr)
 	, body1(body1)
 	, body2(nullptr)
@@ -50,7 +50,7 @@ Joint::Joint(Body *body1)
 }
 
 Joint::Joint(Body *body1, Body *body2)
-	: world(body1->world.get())
+	: world(body1->world)
 	, udata(nullptr)
 	, body1(body1)
 	, body2(body2)

+ 4 - 6
src/modules/physics/box2d/World.cpp

@@ -221,7 +221,6 @@ World::World()
 	, destructWorld(false)
 {
 	world = new b2World(b2Vec2(0,0));
-	this->retain(); // The Box2D world holds a reference to this World.
 	world->SetAllowSleeping(true);
 	world->SetContactListener(this);
 	world->SetContactFilter(this);
@@ -236,8 +235,6 @@ World::World(b2Vec2 gravity, bool sleep)
 	, destructWorld(false)
 {
 	world = new b2World(Physics::scaleDown(gravity));
-	// The Box2D world holds a reference to this World.
-	this->retain();
 	world->SetAllowSleeping(sleep);
 	world->SetContactListener(this);
 	world->SetContactFilter(this);
@@ -249,6 +246,7 @@ World::World(b2Vec2 gravity, bool sleep)
 
 World::~World()
 {
+	destroy();
 }
 
 void World::update(float dt)
@@ -554,6 +552,9 @@ int World::rayCast(lua_State *L)
 
 void World::destroy()
 {
+	if (world == nullptr)
+		return;
+
 	if (world->IsLocked())
 	{
 		destructWorld = true;
@@ -578,9 +579,6 @@ void World::destroy()
 	Memoizer::remove(world);
 	delete world;
 	world = nullptr;
-
-	// Box2D world destroyed. Release its reference.
-	this->release();
 }
 
 } // box2d