open_toontown_panda3d/panda/src/gobj/adaptiveLru.h

212 lines
6.4 KiB
C++

// Filename: adaptiveLru.h
// Created by: drose (03Sep08)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef ADAPTIVELRU_H
#define ADAPTIVELRU_H
#include "pandabase.h"
#include "linkedListNode.h"
#include "namable.h"
#include "lightMutex.h"
#include "lightMutexHolder.h"
class AdaptiveLruPage;
// See the comment in the head of AdaptiveLruPage, below, for an
// explanation of these two silly little classes.
class EXPCL_PANDA_GOBJ AdaptiveLruPageDynamicList : public LinkedListNode {
public:
friend class AdaptiveLru;
};
class EXPCL_PANDA_GOBJ AdaptiveLruPageStaticList : public LinkedListNode {
public:
friend class AdaptiveLru;
};
////////////////////////////////////////////////////////////////////
// Class : AdaptiveLru
// Description : A basic LRU-type algorithm, except that it is
// adaptive and attempts to avoid evicting pages that
// have been used more frequently (even if less
// recently) than other pages.
//
// The interface is designed to be identical to that for
// SimpleLru, so that it may be used as a drop-in
// replacement.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_GOBJ AdaptiveLru : public Namable {
PUBLISHED:
AdaptiveLru(const string &name, size_t max_size);
~AdaptiveLru();
INLINE size_t get_total_size() const;
INLINE size_t get_max_size() const;
INLINE void set_max_size(size_t max_size);
size_t count_active_size() const;
INLINE void consider_evict();
INLINE void evict_to(size_t target_size);
void begin_epoch();
INLINE bool validate();
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
// The following methods are specific to AdaptiveLru, and do not
// exist in the SimpleLru implementation. In most cases, the
// defaults will be sufficient, so you do not need to mess with
// them.
INLINE void set_weight(float weight);
INLINE float get_weight() const;
INLINE void set_max_updates_per_frame(int max_updates_per_frame);
INLINE int get_max_updates_per_frame() const;
private:
public: // temp hack
enum LruPagePriority {
LPP_Highest = 0,
LPP_High = 10,
LPP_New = 20,
LPP_Normal = 25,
LPP_Intermediate = 30,
LPP_Low = 40,
LPP_TotalPriorities = 50,
};
INLINE float calculate_exponential_moving_average(float value, float average) const;
void do_partial_lru_update(int num_updates);
void update_page(AdaptiveLruPage *page);
void do_add_page(AdaptiveLruPage *page);
void do_remove_page(AdaptiveLruPage *page);
void do_access_page(AdaptiveLruPage *page);
void do_evict_to(size_t target_size, bool hard_evict);
bool do_validate();
LightMutex _lock;
size_t _total_size;
size_t _max_size;
unsigned int _current_frame_identifier;
double _weight;
int _max_updates_per_frame;
// This array of linked lists keeps all of the active pages, grouped
// by priority. We reshuffle pages among these lists as they are
// accessed and as they change priority in update_page().
AdaptiveLruPageDynamicList _page_array[LPP_TotalPriorities];
// This linked list keeps all of the active pages, in arbitrary
// order. This list exists solely to allow us to incrementally
// update pages without having to iterate through the complex lists
// above and worry about losing our place. New pages are added to
// the tail. We also move pages from the head to the tail of this
// list in do_partial_lru_update() as we process each page with
// update_page(). Pages do not move within this list other that
// that.
AdaptiveLruPageStaticList _static_list;
friend class AdaptiveLruPage;
};
////////////////////////////////////////////////////////////////////
// Class : AdaptiveLruPage
// Description : One atomic piece that may be managed by a AdaptiveLru
// chain. To use this class, inherit from it and
// override evict_lru().
//
// This class multiply inherits from two classes which
// in turn both inherit from LinkedListNode. This is
// just a sneaky C++ trick to allow this class to
// inherit from LinkedListNode twice, so that pages can
// be stored on two different linked lists
// simultaneously. The AdaptiveLru class depends on
// this; it maintains its pages in two different lists,
// one grouped by priority, and one in order by next
// partial update needs.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_GOBJ AdaptiveLruPage : public AdaptiveLruPageDynamicList, public AdaptiveLruPageStaticList {
PUBLISHED:
AdaptiveLruPage(size_t lru_size);
AdaptiveLruPage(const AdaptiveLruPage &copy);
void operator = (const AdaptiveLruPage &copy);
virtual ~AdaptiveLruPage();
INLINE AdaptiveLru *get_lru() const;
void enqueue_lru(AdaptiveLru *lru);
INLINE void dequeue_lru();
INLINE void mark_used_lru() const;
INLINE void mark_used_lru(AdaptiveLru *lru);
INLINE size_t get_lru_size() const;
INLINE void set_lru_size(size_t lru_size);
virtual void evict_lru();
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
// Not defined in SimpleLruPage.
unsigned int get_num_frames() const;
unsigned int get_num_inactive_frames() const;
private:
AdaptiveLru *_lru;
size_t _lru_size;
int _priority;
unsigned int _first_frame_identifier; // Frame first added.
unsigned int _current_frame_identifier; // Frame last accessed.
unsigned int _update_frame_identifier; // Frame last updated.
int _current_frame_usage;
int _last_frame_usage;
int _total_usage;
int _update_total_usage;
float _average_frame_utilization;
friend class AdaptiveLru;
};
inline ostream &operator << (ostream &out, const AdaptiveLru &lru) {
lru.output(out);
return out;
}
inline ostream &operator << (ostream &out, const AdaptiveLruPage &page) {
page.output(out);
return out;
}
#if 0
BEGIN_PUBLISH
void test_adaptive_lru();
END_PUBLISH
#endif
#include "adaptiveLru.I"
#endif