- documents are now refcounted. This should seriously stabilize (and speed up!) the pruning of unused files

Sun, 22 Dec 2013 20:44:46 +0200

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Sun, 22 Dec 2013 20:44:46 +0200
changeset 583
4906c5c1670f
parent 582
5510207c2396
child 584
12caa4e7b874

- documents are now refcounted. This should seriously stabilize (and speed up!) the pruning of unused files

ldforge.pro file | annotate | diff | comparison | revisions
src/document.cc file | annotate | diff | comparison | revisions
src/document.h file | annotate | diff | comparison | revisions
src/ldtypes.cc file | annotate | diff | comparison | revisions
src/ldtypes.h file | annotate | diff | comparison | revisions
src/misc.cc file | annotate | diff | comparison | revisions
src/misc.h file | annotate | diff | comparison | revisions
src/property.h file | annotate | diff | comparison | revisions
--- a/ldforge.pro	Sat Dec 21 02:21:07 2013 +0200
+++ b/ldforge.pro	Sun Dec 22 20:44:46 2013 +0200
@@ -16,7 +16,7 @@
 RCC_DIR         = ./build_shared/
 UI_DIR          = ./build_shared/
 SOURCES         = src/*.cc
-HEADERS         = src/*.h
+HEADERS         = src/*.h src/misc/*.h
 FORMS           = ui/*.ui
 QT             += opengl network
 QMAKE_CXXFLAGS += -std=c++0x
--- a/src/document.cc	Sat Dec 21 02:21:07 2013 +0200
+++ b/src/document.cc	Sun Dec 22 20:44:46 2013 +0200
@@ -14,11 +14,6 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *  =====================================================================
- *
- *  file.cpp: File I/O and management.
- *  - File loading, parsing, manipulation, saving, closing.
- *  - LDraw path verification.
  */
 
 #include <QMessageBox>
@@ -43,8 +38,8 @@
 static bool g_loadingMainFile = false;
 static const int g_maxRecentFiles = 10;
 static bool g_aborted = false;
-static LDDocument* g_logoedStud = null;
-static LDDocument* g_logoedStud2 = null;
+static LDDocumentPointer g_logoedStud = null;
+static LDDocumentPointer g_logoedStud2 = null;
 
 LDDocument* LDDocument::m_curdoc = null;
 
@@ -113,8 +108,7 @@
 // =============================================================================
 // -----------------------------------------------------------------------------
 LDDocument::LDDocument()
-{	setBeingDeleted (false);
-	setImplicit (true);
+{	setImplicit (true);
 	setSavePosition (-1);
 	setListItem (null);
 	setHistory (new History);
@@ -128,7 +122,6 @@
 	// a ton of other functions will think this file is still valid when it is not!
 	g_loadedFiles.removeOne (this);
 
-	setBeingDeleted (true);
 	m_History->setIgnoring (true);
 
 	// Clear everything from the model
@@ -165,7 +158,6 @@
 	elif (this == g_logoedStud2)
 		g_logoedStud2 = null;
 
-	closeUnused();
 	g_win->updateDocumentList();
 	log ("Closed %1", getName());
 }
@@ -912,9 +904,6 @@
 		if (obj->getType() == LDObject::Error)
 			obj->replace (parseLine (static_cast<LDError*> (obj)->contents));
 	}
-
-	// Close all files left unused
-	LDDocument::closeUnused();
 }
 
 // =============================================================================
@@ -999,63 +988,12 @@
 }
 
 // =============================================================================
-// -----------------------------------------------------------------------------
-static void getFilesUsed (LDDocument* node, QList<LDDocument*>& filesUsed)
-{	filesUsed << node;
-
-	for (LDObject* obj : node->getObjects())
-	{	if (obj->getType() != LDObject::Subfile)
-			continue;
-
-		LDSubfile* ref = static_cast<LDSubfile*> (obj);
-		filesUsed << ref->getFileInfo();
-		getFilesUsed (ref->getFileInfo(), filesUsed);
-	}
-}
-
-// =============================================================================
-// Find out which files are unused and close them.
-// -----------------------------------------------------------------------------
-static bool g_closingUnusedFiles = false;
-
-static void reallyCloseUnused()
-{	// Don't go here more than once at a time, otherwise we risk double-deletions
-	if (g_closingUnusedFiles)
-		return;
-
-	QList<LDDocument*> filesUsed;
-	g_closingUnusedFiles = true;
-
-	// Anything that's explicitly opened must not be closed.
-	// Also do not close anything used by anything explicit
-	for (LDDocument* file : g_loadedFiles)
-		if (!file->isImplicit())
-			getFilesUsed (file, filesUsed);
-
-	// Savor the logoed studs if we use them
-	if (gl_logostuds && g_logoedStud && g_logoedStud2)
-	{	getFilesUsed (g_logoedStud, filesUsed);
-		getFilesUsed (g_logoedStud2, filesUsed);
-	}
-
-	// Remove duplicated entries
-	removeDuplicates (filesUsed);
-
-	// Close all open files that aren't in filesUsed
-	for (LDDocument* file : g_loadedFiles)
-		if (!filesUsed.contains (file))
-			delete file;
-
-	g_closingUnusedFiles = false;
-}
-
-// =============================================================================
+// Close all implicit files with no references
 // -----------------------------------------------------------------------------
 void LDDocument::closeUnused()
-{	// Close unused files later on in the event loop. This function sees a lot of
-	// calls, this reduces the amount of unneeded calls and prevents the engine
-	// from beginning to close unused files when it really shouldn't be doing that.
-	invokeLater (reallyCloseUnused);
+{	for (LDDocument* file : g_loadedFiles)
+		if (file->isImplicit() && file->numReferences() == 0)
+			delete file;
 }
 
 // =============================================================================
@@ -1290,4 +1228,19 @@
 		shortname.prepend (topdirname + "\\");
 
 	return shortname;
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+void LDDocument::addReference (LDDocumentPointer* ptr)
+{	m_refs << ptr;
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+void LDDocument::removeReference (LDDocumentPointer* ptr)
+{	m_refs.removeOne (ptr);
+
+	if (m_refs.size() == 0)
+		invokeLater (closeUnused);
 }
\ No newline at end of file
--- a/src/document.h	Sat Dec 21 02:21:07 2013 +0200
+++ b/src/document.h	Sun Dec 22 20:44:46 2013 +0200
@@ -26,6 +26,7 @@
 
 class History;
 class OpenProgressDialog;
+class LDDocumentPointer;
 
 namespace LDPaths
 {	void initPaths();
@@ -62,8 +63,7 @@
 		PROPERTY (public,		bool,					Implicit,		BOOL_OPS,	STOCK_WRITE)
 		PROPERTY (public,		QList<LDObject*>,	Cache,			NO_OPS,		STOCK_WRITE)
 		PROPERTY (public,		long,					SavePosition,	NUM_OPS,		STOCK_WRITE)
-		PROPERTY (public,		QListWidgetItem*, ListItem,		NO_OPS,		STOCK_WRITE)
-		PROPERTY (private,	bool,					BeingDeleted,	BOOL_OPS,	STOCK_WRITE)
+		PROPERTY (public,		QListWidgetItem*,	ListItem,		NO_OPS,		STOCK_WRITE)
 
 	public:
 		LDDocument();
@@ -84,6 +84,9 @@
 		void swapObjects (LDObject* one, LDObject* other);
 		bool isSafeToClose(); // Perform safety checks. Do this before closing any files!
 		void setObject (int idx, LDObject* obj);
+		void addReference (LDDocumentPointer* ptr);
+		void removeReference (LDDocumentPointer* ptr);
+		int numReferences() const { return m_refs.size(); }
 
 		inline LDDocument& operator<< (LDObject* obj)
 		{	addObject (obj);
@@ -125,9 +128,10 @@
 		friend class LDObject;
 
 	private:
-		QList<LDObject*>			m_sel;
+		QList<LDObject*>				m_sel;
+		QList<LDDocumentPointer*>	m_refs;
 
-		static LDDocument*		m_curdoc;
+		static LDDocument*			m_curdoc;
 };
 
 inline LDDocument* getCurrentDocument()
--- a/src/ldtypes.cc	Sat Dec 21 02:21:07 2013 +0200
+++ b/src/ldtypes.cc	Sun Dec 22 20:44:46 2013 +0200
@@ -263,10 +263,7 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDSubfile::~LDSubfile()
-{	// The document this subfile referenced may be unused now, delete if needed.
-	LDDocument::closeUnused();
-}
+LDSubfile::~LDSubfile() {}
 
 // =============================================================================
 // -----------------------------------------------------------------------------
--- a/src/ldtypes.h	Sat Dec 21 02:21:07 2013 +0200
+++ b/src/ldtypes.h	Sun Dec 22 20:44:46 2013 +0200
@@ -21,6 +21,7 @@
 
 #include "main.h"
 #include "types.h"
+#include "misc/documentPointer.h"
 
 #define LDOBJ(T) \
 protected: \
@@ -377,7 +378,7 @@
 	LDOBJ_COLORED
 	LDOBJ_SCEMANTIC
 	LDOBJ_HAS_MATRIX
-	PROPERTY (public,	LDDocument*, FileInfo, NO_OPS,	STOCK_WRITE)
+	PROPERTY (public,	LDDocumentPointer, FileInfo, NO_OPS,	STOCK_WRITE)
 
 	public:
 		enum InlineFlag
--- a/src/misc.cc	Sat Dec 21 02:21:07 2013 +0200
+++ b/src/misc.cc	Sun Dec 22 20:44:46 2013 +0200
@@ -23,9 +23,12 @@
 #include "misc.h"
 #include "gui.h"
 #include "dialogs.h"
+#include "document.h"
 #include "ui_rotpoint.h"
 #include "moc_misc.cpp"
 
+#include "misc/documentPointer.cc"
+
 RingFinder g_RingFinder;
 
 // Prime number table.
--- a/src/misc.h	Sat Dec 21 02:21:07 2013 +0200
+++ b/src/misc.h	Sun Dec 22 20:44:46 2013 +0200
@@ -26,6 +26,7 @@
 
 #define NUM_PRIMES 500
 
+class LDDocument;
 class QColor;
 class QAction;
 
--- a/src/property.h	Sat Dec 21 02:21:07 2013 +0200
+++ b/src/property.h	Sun Dec 22 20:44:46 2013 +0200
@@ -94,6 +94,12 @@
 			set##NAME( tmp );											\
 		}																	\
 																			\
+		void removeFrom##NAME( const TYPE::value_type& a )	\
+		{	TYPE tmp( m_##NAME );									\
+			tmp.removeOne( a );										\
+			set##NAME( tmp );											\
+		}																	\
+																			\
 		inline void clear##NAME()									\
 		{	set##NAME( TYPE() );										\
 		}

mercurial