Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Boost.Flyweight Documentation - Tutorial - Configuring Boost.Flyweight

Boost , , Boost.Flyweight Documentation - Tutorial

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Boost.Flyweight Tutorial: Configuring Boost.Flyweight



Contents

Configurable aspects of Boost.Flyweight

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

Тип метки.
  • Фабрикаиспользуется для хранения общих значенийflyweightобъектов.
  • Механизм инстанцированияфабрики по производству мухоловок.
  • Внутренниймеханизм синхронизациидля доступа к внутреннему заводу в многопоточной среде.
  • Политика отслеживания, контролирующая, как обрабатывается стоимость, хранящаяся на заводе, когда все связанные с ней объекты с массой тела уничтожаются.
  • [ORIG_END] -->

    Free-order template parameter interface

    Шаблон класса flyweight имеет «умный» интерфейс спецификации, с помощью которого аспекты конфигурации могут быть предоставлены в качестве дополнительных аргументов шаблона в любом порядке, который нравится пользователю. Например, тег flyweight std::strings с set-based factory и no tracking можно указать следующим образом:

    flyweight<std::string, tag<label_t>,  set_factory<>, no_tracking   >
    

    или вот так:

    flyweight<std::string, no_tracking,   tag<label_t>,  set_factory<> >
    

    или в любом другом порядке; только std::string требуется, чтобы занять первое место в спецификации.

    Header inclusion

    В примере кода, показанном в вводном разделе , используется "boost/flyweight.hpp" удобный заголовок, который просто включает заголовки для шаблона класса flyweight и его компонентов конфигурации по умолчанию:

    #include <boost/flyweight/flyweight.hpp>      // class template flyweight
    #include <boost/flyweight/hashed_factory.hpp> // hashed flyweight factory
    #include <boost/flyweight/static_holder.hpp>  // regular factory instantiation
    #include <boost/flyweight/simple_locking.hpp> // simple locking policy
    #include <boost/flyweight/refcounted.hpp>     // refcounting tracking policy
    

    При использовании других компонентов их конкретные заголовки должны быть явно включены.

    Tagging

    Рассмотрим следующие два типа:

    typedef flyweight<std::string> name_t;
    typedef flyweight<std::string> ip_address_t;
    

    Хотя технически оба типа идентичны, это так в силу совпадения, поскольку нет разумной связи между именами и IP-адресами. Внутренне тот факт, что name_t и ip_address_t являются одним и тем же типом веса, приводит к тому, что значения обоих классов хранятся вместе на одной и той же фабрике, хотя их соответствующие диапазоны, как ожидается, не пересекаются. Тагирование может быть использовано, чтобы превратить их в действительно разные типы:

    struct name_tag{};
    typedef flyweight<std::string,tag<name_tag> > name_t;
    struct ip_address_tag{};
    typedef flyweight<std::string,tag<ip_address_tag> > ip_address_t;
    

    Теперь name_t и ip_address_t представляют собой разные классы веса, имеющие отдельные заводы. Теги являются чисто синтаксическим устройством: любой тип может использоваться для маркировки внутри конструкции tag, хотя хороший стиль рекомендует использовать классы тегов с описательными именами, которые являются локальными в контексте, где определяется тип веса.

    Factory specification

    flyweight использует тип внутреннего компонента factory Цель которых состоит в том, чтобы хранить и извлекать различные значения, на которые ссылаются объекты в данный момент времени. По умолчанию используется фабрика на основе хешированного контейнера, так что flyweight фактически эквивалентно

    flyweight<T,hashed_factory<> >
    

    где hashed_factory — так называемый factory specifier. Повышаю. Flyweight предоставляет несколько предопределенных заводских спецификаторов, которые не только позволяют пользователю выбирать конкретный тип используемой фабрики, но и принимают свои собственные шаблонные аргументы для настройки каждой фабрики.

    Types involved in the configuration of factories

    Заданное значение flyweight имеет ассоциированные flyweight::key_type и flyweight::value_type типы (которые равны в случае обычных flyweights или различны, если используются key-value flyweights). Кроме того, существует внутренний тип Entry, который соответствует типу объектов, фактически хранящихся на заводе: Entry содержит общие value_type объекты flyweight, а также некоторую внутреннюю бухгалтерскую информацию; также, Entry неявно конвертируем в const key_type&, так что заводы могут полагаться на key_type, чтобы искать Entries. Поскольку Entry является внутренним для реализации flyweight, пользователь не может напрямую ссылаться на него в конфигурации заводов. Вместо этого можно использовать прокси placeholder type boost::mpl::_1.

    hashed_factory

    Header: "boost/flyweight/hashed_factory.hpp"
    Syntax: hashed_factory<[Hash[,Pred[,Allocator]]]>

    Это спецификатор, который повышает. Flyweight принимает по умолчанию, контролирует использование фабрики на внутренней основе в хеш-контейнере. Значения определяются как эквивалентные с помощью Binary Predicate Pred и индексируются в заводской контейнер с использованием Hash, которая, как предполагается, является функцией hash, т.е. Unary Function присваивая каждому значению хеш-идентификатор типа std::size_t. Параметр Allocator используется заводским контейнером для распределения памяти. Типы по умолчанию для этих параметров такие, что выражение

    flyweight<T,hashed_factory<> >
    

    является эквивалентным

    flyweight<
      T,
      hashed_factory<
        boost::hash<key_value>,
        std::equal_to<key_value>,
        std::allocator<boost::mpl::_1>
      >
    >
    

    где key_type является ключевым типом мухоловки и boost::mpl:::1, как объяснено выше, обозначает внутренний Entry тип элементов, хранящихся на заводе. Предположим, что мы хотели бы настроить hashed_factory для std::string flyweight со специальным хеш-предикатом special_hash и пользовательским распределителем custom_allocator; это будет указано следующим образом:

    flyweight<
      std::string,
      hashed_factory<
        special_hash<std::string>,
        std::equal_to<key_value>,
        custom_allocator<boost::mpl::_1>
      >
    >
    

    set_factory

    Header: "boost/flyweight/set_factory.hpp"
    Syntax: set_factory<[Compare[,Allocator]]>

    set_factory прибегает к std::set-подобному упорядоченному контейнеру для реализации фабрики. Сравнение должно быть Строгая слабая упорядочивание по типу значения flyweight действует; как это принято в контейнерах, заказанных STL, два значения считаются эквивалентными, если ни одно не меньше другого согласно Pred. Allocator - тип распределителя, передаваемый заводскому внутреннему контейнеру для выполнения задач, связанных с памятью. Когда используются параметры по умолчанию, выражение

    flyweight<T,set_factory<> >
    

    является эквивалентным

    flyweight<
      T,
      set_factory<std::less<key_type>,std::allocator<boost::mpl::_1> >
    >
    

    Обычные компромиссы, возникающие при сравнении упорядоченных и хешированных контейнеров, также применяются при выборе между set_factory и hashed_factory: так, поиск на основе набора и вставка значений, как правило, медленнее, чем те, которые основаны на хешировании, но на последнем могут влиять патологические наихудшие сценарии с очень плохой производительностью.

    assoc_container_factory

    Header: "boost/flyweight/assoc_container_factory.hpp"
    Syntax: assoc_container_factory<ContainerSpecifier>

    Этот спецификатор можно рассматривать как обобщение hashed_factory и set_factory, где пользователь поставляет точный тип контейнера, на котором основана фабрика. Способ указания контейнера может показаться сначала немного пугающим для тех, кто не знаком с библиотекой Boost MPL: ContainerSpecifier должен быть MPL Lambda Expression таким, что при вызове с типами Entry и key_type объясняется above, он производит тип контейнера элементов Entry, удовлетворяющий следующим требованиям:

    1. Тип линкераUnique Associative Container,Entry,Entrykey_typeЗначение записи .
    2. Контейнера]стабильного, кабельного и терапического кабеля, дисплея и деформации. Сверх того, что мы знаем, мы знаем, что мы знаем, что мы знаем, что мы знаем, что мы знаем, что мы знаем, что мы знаем.
    Тип контейнера должен быть модельюUnique Associative Container, где эквивалентностьEntrys определяется значениямиkey_type, к которым могут быть конвертированы записи.
  • Контейнер должен бытьстабильным, то есть его итераторы должны оставаться действительными после операций вставки и стирания. Обратите внимание, что это условие не удовлетворяется многими существующими реализациями хешированных контейнеров, которые аннулируют итераторы при повторной операции.
  • [ORIG_END] -->

    Давайте посмотрим, как выглядит спецификатор контейнера с примером. Предположим, что у нас есть собственный заказанный контейнер, такой как:

    template<
      typename Elem,
      typename Compare=std::less<Elem>,
      typename Allocator=std::allocator<Elem>
    >
    class ultrafast_set
    {
      ...
    };
    

    Затем ultrafast_set можно подключить к assoc_container_factory следующим образом:

    typedef flyweight<
      std::string,
      assoc_container_factory<
        // MPL lambda expression follows
        ultrafast_set<mpl::_1,std::less<std::string> >
      >
    > flyweight_string;
    

    Как было объяснено, mpl::_1 представляет собой так называемый заполнитель MPL, стоящий в качестве «слота», который должен быть заменен Entry внутренним механизмом Boost. Весом. Обратите внимание, что мы не полагались на аргумент по умолчанию ultrafast_set для Compare и вместо этого мы предоставили фиксированную инстанциацию для string::string: это так, потому что требования утверждают, что тип, с которым ContainerSpecifier будет заполнен внутри, конвертируем в const key_type& (здесь const std::string&), и он основан на key_type, что поиск и эквивалентность записей должны быть определены. С другой стороны, аргумент по умолчанию для параметра Allocator работает просто отлично, что более очевидно, если мы запишем его явно:

    typedef flyweight<
      std::string,
      assoc_container_factory<
        ultrafast_set<
          mpl::_1,
          std::less<std::string>,
          std::allocator<mpl::_1>
        >
      >
    > flyweight_string;
    

    Holder specification

    Каждый тип мухоловки, то есть каждое отдельное воплощение шаблона класса мухоловка , связан именно с одним заводским объектом. В большинстве случаев то, как создается этот заводской объект, не имеет большого значения для пользователя Boost. Вес, но есть особые обстоятельства, когда контроль над этим аспектом необходим. Внутренний компонент, называемый holder, отвечает за инстанцирование фабричного класса и некоторой другой внутренней информации; этот компонент определяется с помощью holder specifier, static_holder по умолчанию.

    static_holder

    Header: "boost/flyweight/static_holder.hpp"
    Syntax: static_holder

    Это спецификатор держателя по умолчанию Boost. Flyweight и производит держателей, где уникальный завод живет как локальная статическая переменная программы.

    intermodule_holder

    Header: "boost/flyweight/intermodule_holder.hpp"
    Syntax: intermodule_holder

    В большинстве сред C++ статические переменные плохо смешиваются с динамически загружаемыми модулями в том смысле, что экземпляры одной и той же статической переменной могут дублироваться в разных модулях, хотя по определению переменная должна быть уникальной. Во многих случаях это дублирование остается незамеченным, если модули не взаимодействуют друг с другом с использованием затронутых типов, но рассмотрим случай, когда такая связь действительно происходит:

    // module 1
    typedef flyweight<std::string> flyweight_string;
    // produce_string is exported so that it can be dynamically
    // linked
    flyweight_string produce_string()
    {
      return flyweight_string("boost");
    }
    
    // main program
    typedef flyweight<std::string> flyweight_string;
    int main()
    {
      ... // import module 1
      flyweight_string str1=produce_string();
      flyweight_string str2("boost");
      assert(str1==str2);
    }
    

    Во многих средах эта программа приводит к отказу утверждения, потому что объект фабрики, используемый flyweight_string Как видно в модуле 1, это не тот же заводской объект, как видно в основной программе: следовательно, представления значений, на которые внутренне указывают str1 и str2, будут отличаться и будут ошибочно считаться не равными. Многие другие проблемы могут возникнуть из-за фабричного дублирования, включая неопределенное поведение.

    intermodule_holder определяет заводского владельца, который способен избежать проблемы дублирования и гарантировать, что все модули программы используют один и тот же заводской экземпляр. Чтобы исправить приведенный выше пример, достаточно переопределить flyweight_string в обоих модулях как:

    typedef flyweight<std::string,intermodule_holder> flyweight_string;
    

    intermodule_holder является значительно более обременительным, чем static_holder, с точки зрения времени компиляции и вводит незначительные накладные расходы при запуске программы.

    Locking policies

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

    simple_locking

    Header: "boost/flyweight/simple_locking.hpp"
    Syntax: simple_locking

    Это политика блокировки по умолчанию. Он определяет простейшие нативные примитивы синхронизации, предоставляемые операционной системой, когда это возможно.

    no_locking

    Header: "boost/flyweight/no_locking.hpp"
    Syntax: no_locking

    Никакая синхронизация не обеспечивается для обеспечения неограниченного внутреннего доступа к общим ресурсам реализации. Выбор no_locking приводит к несколько более быстрому выполнению, чем по умолчанию simple_locking, но это делает тип потока небезопасным, что может иметь катастрофические последствия. Эта политика не должна использоваться, кроме как в однопоточной среде или когда есть абсолютная гарантия того, что конкретный вес Тип не будет использоваться в параллельном сценарии.

    Tracking policies

    Политика отслеживания контролирует время жизни объектов flyweight и может действовать на основе этой информации. Например, подходящий механизм отслеживания может определить, когда данное значение, хранящееся на заводе, может быть безопасно удалено, потому что на него больше не ссылаются никакие flyweight; это именно то, что делает политика отслеживания по умолчанию refcounted.

    refcounted

    Header: "boost/flyweight/refcounted.hpp"
    Syntax: refcounted

    Эта политика отслеживания определяет, что значения, хранящиеся на заводе, должны быть оснащены механизмами подсчета ссылок, чтобы запись на заводе была стерта, когда последний объект flyweight, связанный с ним, будет уничтожен.

    no_tracking

    Header: "boost/flyweight/no_tracking.hpp"
    Syntax: no_tracking

    Отслеживание веса не выполняется при выборе этой политики, что означает, что значения, хранящиеся на заводе, остаются в нем до окончания программы. По сравнению с refcounted, no_tracking представляет преимущества и недостатки. Преимущества:

    • Неприятные симптомы, неприятные ощущения, неприятные ощущения.
    • a. , , , , , , , , , , , , , , , , , , .
    в то время как потенциальные недостатки использования no_tracking включают:
    • ?????????????????????
    • "Воздушная волна", "Воздушная волна", "Воздушная волна".
    Не отслеживаемые объекты в весе летают быстрее, чем пересчитанные.
  • Существует некоторое сокращение использования памяти из-за отсутствия счетчиков отсчета.
  • whereas potential drawbacks of using no_tracking include:
    • Количество неиспользуемых записей, хранящихся на заводе, может продолжать расти в течение срока службы программы, что может стать проблемой для определенных моделей создания веса, где набор активных значений «дрейфует» с течением времени.
    • Возможна задержка при прекращении программы, так как именно тогда все заводские записи уничтожаются сразу.
    [ORIG_END] -->




    Пересмотрено 8 ноября 2008 года

    © Copyright 2006-2008 Joaquín M López Muñoz. Распространяется под лицензией Boost Software License, версия 1.0. (См. сопроводительный файл) LICENSE_1_0.txt или копировать на http://www.boost.org/LICENSE_1_0.txt

    Статья Boost.Flyweight Documentation - Tutorial - Configuring Boost.Flyweight раздела Boost.Flyweight Documentation - Tutorial может быть полезна для разработчиков на c++ и boost.




    Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



    :: Главная :: Boost.Flyweight Documentation - Tutorial ::


    реклама


    ©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
    Top.Mail.Ru

    Время компиляции файла: 2024-08-30 11:47:00
    2025-07-05 02:20:30/0.0089240074157715/0