[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi] [PATCH 1/5] Add loaded_files_cache<T> class
From: |
Vaclav Slavik |
Subject: |
[lmi] [PATCH 1/5] Add loaded_files_cache<T> class |
Date: |
Fri, 15 Jun 2012 18:19:06 +0200 |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20120601 Thunderbird/13.0 |
Hi,
this is the first in a series of patches that implement caching of
xml_actuarial_table and DBDictionary. This one adds the reusable caching
class we discussed.
The class checks for modified files automatically. Types used with it
must implement a T(filename) constructor; I think that's the simplest
and most natural way of constructing objects from file data.
I ended up using pointers in the end, because DBDictionary is uncopyable
-- and unlike xml_actuarial_table, cannot be easily made copyable. I use
shared_ptr<> instead of raw pointers for ease of destruction and I use
shared_ptr<> instead of some other form of pointers because it neatly
solves another problem: an entry in the cache could be invalidated by
another access if the underlying file changed. But that shouldn't affect
the instance already retrieved (nor should a pointer to a cached copy
used somewhere suddenly become invalid) and shared pointers solve that
neatly.
Regards,
Vaclav
---
loaded_files_cache.hpp | 118 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/loaded_files_cache.hpp b/loaded_files_cache.hpp
new file mode 100644
index 0000000..d7bde11
--- /dev/null
+++ b/loaded_files_cache.hpp
@@ -0,0 +1,118 @@
+// Caching of loaded files.
+//
+// Copyright (C) 2012 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+// $Id$
+
+#ifndef loaded_files_cache_hpp
+#define loaded_files_cache_hpp
+
+#include "config.hpp"
+
+#include "uncopyable_lmi.hpp"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <map>
+
+/// Cache of objects loaded from files.
+///
+/// Used for holding objects that are expensively loaded from a file in memory.
+/// For example, loading actuarial_table from an XML file is costly, so we keep
+/// loaded instances in memory until the program terminates or until the file
+/// is modified.
+///
+/// T must have a constructor that takes a single string argument, the
+/// filename, as well as the default constructor.
+template<typename T>
+class loaded_files_cache
+ :private lmi::uncopyable< loaded_files_cache<T> >
+{
+ public:
+ typedef T value_type;
+ typedef boost::shared_ptr<value_type const> value_ptr_type;
+ typedef std::string key_type;
+
+ // Get object corresponding to the given file, either getting it from the
+ // cache or loading from the file. Checks file's timestamp and reloads it
+ // if it was modified since the cached copy was read.
+ value_ptr_type get(key_type const& filename)
+ {
+ std::time_t const write_time = fs::last_write_time(filename);
+
+ typename map_type::iterator i = cache_.lower_bound(filename);
+ if
+ ( i != cache_.end()
+ && i->first == filename
+ && write_time == i->second.write_time
+ )
+ {
+ return i->second.data;
+ }
+
+ // create the value before calling insert() because the call may throw
+ value_ptr_type value(new value_type(filename));
+
+ // insert() doesn't update the value if the key is already present, so
+ // insert a dummy value and then modify it -- this will work for both
+ // existing and new keys.
+ i = cache_.insert(i, typename map_type::value_type(filename,
record()));
+ record& rec = i->second;
+ rec.write_time = write_time;
+ rec.data = value;
+
+ return value;
+ }
+
+ // Return singleton instance of the cache.
+ static loaded_files_cache& instance()
+ {
+ static loaded_files_cache inst;
+ return inst;
+ }
+
+ private:
+ struct record
+ {
+ std::time_t write_time;
+ value_ptr_type data;
+ };
+
+ typedef std::map<key_type, record> map_type;
+ map_type cache_;
+};
+
+/// Base class for cached types.
+/// Its only purpose is providing convenience get_cached() function.
+template<typename T>
+class loaded_from_cache
+{
+ public:
+ typedef loaded_files_cache<T> cache_type;
+ typedef typename cache_type::value_ptr_type ptr_type;
+
+ static ptr_type get_cached(std::string const& filename)
+ {
+ return cache_type::instance().get(filename);
+ }
+};
+
+#endif // loaded_files_cache_hpp
--
1.7.10.4
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi] [PATCH 1/5] Add loaded_files_cache<T> class,
Vaclav Slavik <=