Обобщенный подключаемый шаблон кэширования? - PullRequest
8 голосов
/ 27 апреля 2010

Учитывая, что это одна из трудных вещей в информатике , кто-нибудь знает, как настроить подключаемую стратегию кэширования?

То, о чем я думаю, позволило бы мне написать программу с минимальным вниманием к тому, что нужно кэшировать (например, использовать какой-то шаблон, шаблон низкой / бесплатной стоимости, который компилируется ни с чем, где бы я ни захотел) кэширование), а затем, когда дела идут дальше, и я знаю, где мне нужно кэширование, я могу добавить его, не внося инвазивных изменений в код.

Как идея того решения, которое я ищу; Я работаю с D языком программирования (но на полпути нормальный C ++ будет в порядке), и мне нравится шаблон.

Ответы [ 4 ]

1 голос
/ 28 июля 2011

есть решение c ++ 0x для общего автоматического запоминания (см. Ответ здесь: Каковы разумные способы улучшить решение рекурсивных задач? )

1 голос
/ 27 апреля 2010

Ближайшая вещь, которая приходит мне в голову - это запоминание чистых функций. Возможно, вам также будет интересна эта книга Управление шаблонами в архитектуре программного обеспечения на основе шаблонов , в которой есть шаблон кэширования.

0 голосов
/ 13 мая 2010

Я не уверен, в какой степени решение должно быть «обобщенным» и «подключаемым», но если вы можете позволить себе рефакторинг использования ваших кэшей (замена вызовов функций прямым использованием какой-либо переменной), то подумайте о следующем :

//works for any CopyConstructible type of cache and any function 
//which result should be cached 
//(the arguments of the function have to be properly binded)
/**
* caching + lazy initialization
* we shouldn't allow copying of lazy<T>, because every copy initializes its own cache
* and this is not what intended most of the time
* T must be CopyConstructible
*/
template<class T>
class lazy: private boost::noncopyable
{
public:
    lazy(boost::function0<T> _creator)
        : creator(_creator) {}
    /**
    * aka is_cashed
    */
    bool is_initialized()
    {
        return val;
    }
    operator T&()
    {
        if(!val)
            val = creator();
        return *val;
    }
    T& operator*()
    {
        if(!val)
            val = creator();
        return *val;
    }
    /**
    * resets cache to update it next time it is used
    */
    void reset()
    {
        val.reset();
    }
private:
    boost::function0<T> creator;
    boost::optional<T> val;
};
//usage
    //initialize caching and updating strategy
    lazy<WebPage> cached_page(boost::bind(&Server::getPage, server));
    server->OnPageUpdate = boost::bind(&OnPageUpdate, cached_page);
    .....

    //use cached_page everywhere as if it were regular variable of WebPage type
    showPage(cached_page);
//--------------
void OnPageUpdate(lazy<WebPage>& page)
{
    page.reset();
}

Если вы хотите удалить отложенную инициализацию, измените ее так, чтобы в конструкторе был создан кеш, а метод reset ().

0 голосов
/ 11 мая 2010

Вас может заинтересовать, как Drizzle делает подобные вещи с различными бэкэндами хранения и кэширования. В двух словах, он предоставляет интерфейс, который может использоваться родительским приложением для взаимодействия с MySQL, memcached и т. Д.

...