# # # patch "transforms.cc" # from [5ddd45879695306827570bd595789564990540fd] # to [fe810b3b1a64cd928b5a55a8b38182c35e21ab6c] # # patch "vocab.hh" # from [61bc19598cbf8668c41855cfa0841af03079be30] # to [4bb5ac94de37c2d875e2d3eed3f0d1b64b59a429] # ============================================================ --- transforms.cc 5ddd45879695306827570bd595789564990540fd +++ transforms.cc fe810b3b1a64cd928b5a55a8b38182c35e21ab6c @@ -9,6 +9,7 @@ #include "base.hh" #include +#include #include #include ============================================================ --- vocab.hh 61bc19598cbf8668c41855cfa0841af03079be30 +++ vocab.hh 4bb5ac94de37c2d875e2d3eed3f0d1b64b59a429 @@ -10,36 +10,54 @@ #ifndef __VOCAB_HH__ #define __VOCAB_HH__ -#include - #include "sanity.hh" +#include "intrusive_ptr.hh" +#include // the purpose of this file is to wrap things which are otherwise strings // in a bit of typesafety, set up enumerations and tuple-types, and // generally describe the "vocabulary" (nouns anyways) that modules in this // program use. -// For some reason, shared_ptr copy is about a hundred times faster -// than string refcopy on my system (g++ 4). This only happens because -// we tell Boost not to worry about threads... but I don't recognize any -// thread stuff in the string headers. +// Vocab strings are immutable once constructed, and references to them are +// extensively copied around. We don't know whether the standard string is +// copy-on-write, and even if it is, that mechanism has surprising overhead +// due to thread safety (unnecessary for this application) and the large set +// of conditions where it has to unshare. So we wrap the actual string in +// this pair of classes which collectively have immutable, ref-counting +// semantics. +class immutable_string_data : public intrusively_refcounted, + public boost::noncopyable +{ +protected: + std::string const data; +private: + immutable_string_data(); // disallowed +public: + immutable_string_data(std::string const & s) + : data(s) + {} + ~immutable_string_data() {} + std::string const & get() { return data; } +}; + class immutable_string { - boost::shared_ptr _rep; + boost::intrusive_ptr _rep; static std::string empty; public: immutable_string() {} immutable_string(std::string const & s) - : _rep(new std::string(s)) + : _rep(new immutable_string_data(s)) {} std::string const & get() const { if (_rep) - return *_rep; + return _rep->get(); else return empty; }