From: Richard Heck Date: Thu, 6 Mar 2008 23:31:40 +0000 (+0000) Subject: Improve performance of TextClass type objects by making BaseClassList and DocumentCla... X-Git-Tag: 1.6.10~5822 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=6f1cb456cf56d143ad49eb1cd202a1781bfdc0c1;p=features.git Improve performance of TextClass type objects by making BaseClassList and DocumentClassBundle containers of pointers rather than of objects, thus reducing the need to copy. Since these classes are singletons that live the life of the process, there's not much need to worry about memory leaks. We take the opportunity to make TextClass objects noncopyable, nonassignable, etc. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23526 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/BaseClassList.cpp b/src/BaseClassList.cpp index c4da968452..91aeecd599 100644 --- a/src/BaseClassList.cpp +++ b/src/BaseClassList.cpp @@ -69,7 +69,7 @@ bool BaseClassList::haveClass(string const & classname) const LayoutFile const & BaseClassList::operator[](string const & classname) const { BOOST_ASSERT(haveClass(classname)); - return classmap_[classname]; + return *classmap_[classname]; } @@ -77,7 +77,7 @@ LayoutFile & BaseClassList::operator[](string const & classname) { BOOST_ASSERT(haveClass(classname)); - return classmap_[classname]; + return *classmap_[classname]; } @@ -139,11 +139,11 @@ bool BaseClassList::read() LYXERR(Debug::TCLASS, "Avail: " << avail); // This code is run when we have // fname, clname, desc, and avail - LayoutFile tmpl(fname, clname, desc, avail); + LayoutFile * tmpl = new LayoutFile(fname, clname, desc, avail); if (lyxerr.debugging(Debug::TCLASS)) { // only system layout files are loaded here so no // buffer path is needed. - tmpl.load(); + tmpl->load(); } classmap_[fname] = tmpl; } @@ -176,10 +176,12 @@ std::vector BaseClassList::classList() const void BaseClassList::reset(LayoutFileIndex const & classname) { BOOST_ASSERT(haveClass(classname)); - LayoutFile const & tc = classmap_[classname]; - LayoutFile tmpl(tc.name(), tc.latexname(), tc.description(), - tc.isTeXClassAvailable()); + LayoutFile * tc = classmap_[classname]; + LayoutFile * tmpl = + new LayoutFile(tc->name(), tc->latexname(), tc->description(), + tc->isTeXClassAvailable()); classmap_[classname] = tmpl; + delete tc; } @@ -220,13 +222,15 @@ LayoutFileIndex // returns: whole string, classtype (not used here), class name, description BOOST_ASSERT(sub.size() == 4); // now, create a TextClass with description containing path information - LayoutFile tmpl(textclass, sub.str(2) == "" ? textclass : sub.str(2), - sub.str(3) + " <" + path + ">", true); - classmap_[localIndex] = tmpl; + string className(sub.str(2) == "" ? textclass : sub.str(2)); + string description(sub.str(3) + " <" + path + ">"); + LayoutFile * tmpl = + new LayoutFile(textclass, className, description, true); // This textclass is added on request so it will definitely be // used. Load it now because other load() calls may fail if they // are called in a context without buffer path information. - classmap_[localIndex].load(path); + tmpl->load(path); + classmap_[localIndex] = tmpl; return localIndex; } } diff --git a/src/BaseClassList.h b/src/BaseClassList.h index 4f058f6de1..090d5db89f 100644 --- a/src/BaseClassList.h +++ b/src/BaseClassList.h @@ -16,6 +16,8 @@ #include "support/strfwd.h" +#include + #include @@ -45,24 +47,21 @@ private: /// This class amounts to little more than a `strong typedef'. /// A LayoutFile represents the layout information that is /// contained in a *.layout file. -class LayoutFile : public TextClass { +class LayoutFile : public TextClass, boost::noncopyable { public: - /// This should never be used, but it has to be provided for - /// std::map operator[] to work. Something like: - /// mapthingy[stuff] = otherthing - /// creates an empty object before doing the assignment. - LayoutFile() {} /// check whether the TeX class is available bool isTeXClassAvailable() const { return texClassAvail_; } private: /// Construct a layout with default values. Actual values loaded later. - explicit LayoutFile(std::string const &, - std::string const & = std::string(), - std::string const & = std::string(), - bool texClassAvail = false); + explicit LayoutFile(std::string const & filename, + std::string const & className = std::string(), + std::string const & description = std::string(), + bool texClassAvail = false); /// The only class that should create a LayoutFile is /// BaseClassList, which calls the private constructor. friend class BaseClassList; + /// can't create empty LayoutFile + LayoutFile() {}; }; @@ -98,7 +97,7 @@ public: static std::string const localPrefix; private: /// - typedef std::map ClassMap; + typedef std::map ClassMap; /// noncopyable BaseClassList(BaseClassList const &); /// nonassignable diff --git a/src/TextClass.cpp b/src/TextClass.cpp index e47bf0baab..a5ab3e1e0e 100644 --- a/src/TextClass.cpp +++ b/src/TextClass.cpp @@ -989,9 +989,9 @@ bool TextClass::isEmptyLayout(Layout const & lay) const DocumentClass & DocumentClassBundle::newClass(LayoutFile const & baseClass) { - DocumentClass dc(baseClass); + DocumentClass * dc = new DocumentClass(baseClass); tc_list_.push_back(dc); - return tc_list_.back(); + return *tc_list_.back(); } diff --git a/src/TextClass.h b/src/TextClass.h index a465f123ef..281d2e4c1f 100644 --- a/src/TextClass.h +++ b/src/TextClass.h @@ -20,6 +20,7 @@ #include "support/docstring.h" #include "support/types.h" +#include #include #include @@ -37,6 +38,19 @@ class Layout; class LayoutFile; class Lexer; +/// Based upon ideas in boost::noncopyable, inheriting from this +/// class effectively makes the copy constructor protected but the +/// assignment constructor private. +class ProtectCopy +{ +protected: + ProtectCopy() {} + ~ProtectCopy() {} + ProtectCopy(const ProtectCopy &) {}; +private: + const ProtectCopy & operator=(const ProtectCopy &); +}; + /// A TextClass represents a collection of layout information: At the /// moment, this includes Layout's and InsetLayout's. @@ -46,7 +60,7 @@ class Lexer; /// Simple TextClass objects are not directly constructed in the main /// LyX code---the constructor is protected. (That said, in tex2lyx /// there are what amount to simple TextClass objects.) -class TextClass { +class TextClass : protected ProtectCopy { public: /// virtual ~TextClass() {}; @@ -242,7 +256,7 @@ private: /// /// In the main LyX code, DocumentClass objects are created only by /// DocumentClassBundle, for which see below. -class DocumentClass : public TextClass { +class DocumentClass : public TextClass, boost::noncopyable { public: /// virtual ~DocumentClass() {} @@ -328,7 +342,7 @@ protected: DocumentClass() {}; private: /// The only class that can create a DocumentClass is - /// DocumentClassBundle, which calls the private constructor. + /// DocumentClassBundle, which calls the protected constructor. friend class DocumentClassBundle; /// static InsetLayout empty_insetlayout_; @@ -345,7 +359,7 @@ private: /// /// This is a singleton class. Its sole instance is accessed via /// DocumentClassBundle::get(). -class DocumentClassBundle { +class DocumentClassBundle : boost::noncopyable { public: /// \return Pointer to a new class equal to baseClass DocumentClass & newClass(LayoutFile const & baseClass); @@ -354,10 +368,8 @@ public: private: /// control instantiation DocumentClassBundle() {} - /// noncopyable - DocumentClassBundle(DocumentClassBundle const &); /// - std::list tc_list_; + std::list tc_list_; }; diff --git a/src/tex2lyx/preamble.cpp b/src/tex2lyx/preamble.cpp index aaf434c720..a3d16fccb1 100644 --- a/src/tex2lyx/preamble.cpp +++ b/src/tex2lyx/preamble.cpp @@ -406,7 +406,8 @@ void end_preamble(ostream & os, TextClass const & /*textclass*/) } // anonymous namespace -TeX2LyXDocClass const parse_preamble(Parser & p, ostream & os, string const & forceclass) +void parse_preamble(Parser & p, ostream & os, + string const & forceclass, TeX2LyXDocClass & tc) { // initialize fixed types special_columns['D'] = 3; @@ -661,15 +662,13 @@ TeX2LyXDocClass const parse_preamble(Parser & p, ostream & os, string const & fo cerr << "Error: Could not find layout file for textclass \"" << h_textclass << "\"." << endl; exit(1); } - TeX2LyXDocClass textclass; - textclass.read(layoutfilename); + tc.read(layoutfilename); if (h_papersides.empty()) { ostringstream ss; - ss << textclass.sides(); + ss << tc.sides(); h_papersides = ss.str(); } - end_preamble(os, textclass); - return textclass; + end_preamble(os, tc); } // }]) diff --git a/src/tex2lyx/tex2lyx.cpp b/src/tex2lyx/tex2lyx.cpp index 1170ded8e4..6890b370c8 100644 --- a/src/tex2lyx/tex2lyx.cpp +++ b/src/tex2lyx/tex2lyx.cpp @@ -397,7 +397,8 @@ void tex2lyx(istream & is, ostream & os) //p.dump(); stringstream ss; - TeX2LyXDocClass textclass = parse_preamble(p, ss, documentclass); + TeX2LyXDocClass textclass; + parse_preamble(p, ss, documentclass, textclass); captionlayout = LayoutPtr(Layout::forCaption()); active_environments.push_back("document"); diff --git a/src/tex2lyx/tex2lyx.h b/src/tex2lyx/tex2lyx.h index 2fbb4ec5b6..3a45dbae49 100644 --- a/src/tex2lyx/tex2lyx.h +++ b/src/tex2lyx/tex2lyx.h @@ -35,7 +35,8 @@ class TeX2LyXDocClass : public DocumentClass {}; /// in preamble.cpp -TeX2LyXDocClass const parse_preamble(Parser & p, std::ostream & os, std::string const & forceclass); +void parse_preamble(Parser & p, std::ostream & os, + std::string const & forceclass, TeX2LyXDocClass & tc); /// used packages with options extern std::map > used_packages;