Mercurial > hg > orthanc
comparison OrthancFramework/Sources/Cache/MemoryStringCache.h @ 5420:d37dff2c0028 am-new-cache
Optimized the MemoryStringCache to prevent loading the same file multiple times if multiple users request the same file at the same time
author | Alain Mazy <am@osimis.io> |
---|---|
date | Mon, 13 Nov 2023 17:01:59 +0100 |
parents | 0ea402b4d901 |
children | c65e036d649b |
comparison
equal
deleted
inserted
replaced
5419:ac4e9fb87615 | 5420:d37dff2c0028 |
---|---|
21 **/ | 21 **/ |
22 | 22 |
23 | 23 |
24 #pragma once | 24 #pragma once |
25 | 25 |
26 #include "MemoryObjectCache.h" | 26 #include "../OrthancFramework.h" |
27 #include "ICacheable.h" | |
28 #include "LeastRecentlyUsedIndex.h" | |
29 | |
30 #include <boost/thread/condition_variable.hpp> | |
31 #include <boost/thread/mutex.hpp> | |
32 | |
27 | 33 |
28 namespace Orthanc | 34 namespace Orthanc |
29 { | 35 { |
30 /** | 36 /** |
31 * Facade object around "MemoryObjectCache" that caches a dictionary | 37 * Class that caches a dictionary |
32 * of strings, using the "fetch/add" paradigm of memcached. | 38 * of strings, using the "fetch/add" paradigm of memcached. |
39 * | |
40 * Starting from 1.12.2, if multiple clients are trying to access | |
41 * an inexistent item at the same time, only one of them will load it | |
42 * and the others will wait until the first one has loaded the data. | |
43 * | |
44 * The MemoryStringCache is only accessible through an Accessor. | |
33 * | 45 * |
34 * Note: this class is thread safe | 46 * Note: this class is thread safe |
35 **/ | 47 **/ |
36 class ORTHANC_PUBLIC MemoryStringCache : public boost::noncopyable | 48 class ORTHANC_PUBLIC MemoryStringCache : public boost::noncopyable |
37 { | 49 { |
50 public: | |
51 class Accessor : public boost::noncopyable | |
52 { | |
53 MemoryStringCache& cache_; | |
54 bool shouldAdd_; // when this accessor is the one who should load and add the data | |
55 std::string keyToAdd_; | |
56 public: | |
57 Accessor(MemoryStringCache& cache); | |
58 ~Accessor(); | |
59 | |
60 bool Fetch(std::string& value, const std::string& key); | |
61 void Add(const std::string& key, const std::string& value); | |
62 void Add(const std::string& key,const char* buffer, size_t size); | |
63 }; | |
64 | |
38 private: | 65 private: |
39 class StringValue; | 66 class StringValue; |
40 | 67 |
41 MemoryObjectCache cache_; | 68 boost::mutex cacheMutex_; // note: we can not use recursive_mutex with condition_variable |
69 boost::condition_variable cacheCond_; | |
70 std::set<std::string> itemsBeingLoaded_; | |
71 | |
72 size_t currentSize_; | |
73 size_t maxSize_; | |
74 LeastRecentlyUsedIndex<std::string, StringValue*> content_; | |
75 | |
76 void Recycle(size_t targetSize); | |
42 | 77 |
43 public: | 78 public: |
79 MemoryStringCache(); | |
80 | |
81 ~MemoryStringCache(); | |
82 | |
44 size_t GetMaximumSize(); | 83 size_t GetMaximumSize(); |
45 | 84 |
46 void SetMaximumSize(size_t size); | 85 void SetMaximumSize(size_t size); |
47 | 86 |
87 void Invalidate(const std::string& key); | |
88 | |
89 | |
90 private: | |
48 void Add(const std::string& key, | 91 void Add(const std::string& key, |
49 const std::string& value); | 92 const std::string& value); |
50 | 93 |
51 void Add(const std::string& key, | 94 void Add(const std::string& key, |
52 const void* buffer, | 95 const void* buffer, |
53 size_t size); | 96 size_t size); |
54 | 97 |
55 void Invalidate(const std::string& key); | |
56 | |
57 bool Fetch(std::string& value, | 98 bool Fetch(std::string& value, |
58 const std::string& key); | 99 const std::string& key); |
100 | |
101 void RemoveFromItemsBeingLoaded(const std::string& key); | |
102 void RemoveFromItemsBeingLoadedInternal(const std::string& key); | |
103 | |
104 void AddToItemsBeingLoadedInternal(const std::string& key); | |
59 }; | 105 }; |
60 } | 106 } |