| 1825 | // Future<Void> cancel() const; |
| 1826 | template <class IndexType, class ObjectType> |
| 1827 | class ObjectCache : NonCopyable { |
| 1828 | struct Entry; |
| 1829 | typedef std::unordered_map<IndexType, Entry> CacheT; |
| 1830 | |
| 1831 | struct Entry : public boost::intrusive::list_base_hook<> { |
| 1832 | Entry() : hits(0), size(0) {} |
| 1833 | IndexType index; |
| 1834 | ObjectType item; |
| 1835 | int hits; |
| 1836 | int size; |
| 1837 | bool ownedByEvictor; |
| 1838 | CacheT* pCache; |
| 1839 | }; |
| 1840 | |
| 1841 | typedef boost::intrusive::list<Entry> EvictionOrderT; |
| 1842 | |
| 1843 | public: |
| 1844 | // Object evictor, manages the eviction order for one or more ObjectCaches |
| 1845 | // Not all objects tracked by the Evictor are in its evictionOrder, as ObjectCaches |
| 1846 | // using this Evictor can temporarily remove entries to an external order but they |
| 1847 | // must eventually give them back with moveIn() or remove them with reclaim(). |
| 1848 | class Evictor : NonCopyable { |
| 1849 | public: |
| 1850 | Evictor(int64_t sizeLimit = 0) : sizeLimit(sizeLimit) {} |
| 1851 | |
| 1852 | // Evictors are normally singletons, either one per real process or one per virtual process in simulation |
| 1853 | static Evictor* getEvictor() { |
| 1854 | static Evictor nonSimEvictor; |
| 1855 | static std::map<NetworkAddress, Evictor> simEvictors; |
| 1856 | |
| 1857 | if (g_network->isSimulated()) { |
| 1858 | return &simEvictors[g_network->getLocalAddress()]; |
| 1859 | } else { |
| 1860 | return &nonSimEvictor; |
| 1861 | } |
| 1862 | } |
| 1863 | |
| 1864 | // Move an entry to a different eviction order, stored outside of the Evictor, |
| 1865 | // but the entry size is still counted against the evictor |
| 1866 | void moveOut(Entry& e, EvictionOrderT& dest) { |
| 1867 | ASSERT(e.ownedByEvictor); |
| 1868 | dest.splice(dest.end(), evictionOrder, EvictionOrderT::s_iterator_to(e)); |
| 1869 | e.ownedByEvictor = false; |
| 1870 | ++movedOutCount; |
| 1871 | } |
| 1872 | |
| 1873 | // Move an entry to the back of the eviction order if it is in the eviction order |
| 1874 | void moveToBack(Entry& e) { |
| 1875 | ASSERT(e.ownedByEvictor); |
| 1876 | evictionOrder.splice(evictionOrder.end(), evictionOrder, EvictionOrderT::s_iterator_to(e)); |
| 1877 | } |
| 1878 | |
| 1879 | // Move entire contents of an external eviction order containing entries whose size is part of |
| 1880 | // this Evictor to the front of its eviction order. |
| 1881 | void moveIn(EvictionOrderT& otherOrder) { |
| 1882 | for (auto& e : otherOrder) { |
| 1883 | ASSERT(!e.ownedByEvictor); |
| 1884 | e.ownedByEvictor = true; |
nothing calls this directly
no test coverage detected