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

Writing your own attributes

Boost , Chapter 1. Boost.Log v2 , Extending the library

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

PrevUpHomeNext
#include <boost/log/attributes/attribute.hpp>
#include <boost/log/attributes/attribute_value.hpp>
#include <boost/log/attributes/attribute_value_impl.hpp>

Разработка собственных атрибутов довольно проста. Как правило, вы должны сделать следующее:

  1. Определите, каким будет значение атрибута. Скорее всего, это будет часть постоянных данных, которые вы хотите использовать для фильтрации и форматирования. Переведите эти данные в класс, который происходит из интерфейса impl; это класс реализации значения атрибута. Этот объект должен будет реализовать метод dispatch, который будет извлекать сохраненные данные (или, другими словами, сохраненное значение) в диспетчер типа. В большинстве случаев для этого может использоваться класс attribute_value_impl, предоставляемый библиотекой.
  2. Используйте класс attribute_value в качестве класса интерфейса, который содержит ссылку на реализацию значения атрибута.
  3. Определите, как будут производиться значения атрибутов. В угловом случае значения не должны быть произведены (например, в случае атрибута constant, предоставленного библиотекой), но часто существует некоторая логика, которую необходимо использовать для получения значения атрибута. Эта логика должна быть сконцентрирована в классе, полученном из интерфейса impl, точнее - в методе get_value. Этот класс является классом реализации атрибутов. Вы можете думать об этом как о фабрике по производству атрибутов.
  4. Определите класс интерфейса атрибута, который происходит от атрибута . По соглашению класс интерфейса должен создать соответствующую реализацию на конструировании и передать указатель на него конструктору класса атрибут. Класс интерфейса может иметь методы интерфейса, но, как правило, он не должен содержать никаких элементов данных, поскольку данные будут потеряны при добавлении атрибута в библиотеку. Вместо этого все соответствующие данные должны быть помещены в класс реализации.

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

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

  • Значение атрибута никогда не меняется, поэтому его можно хранить в самом атрибуте. Примером может служить атрибут constant.
  • Атрибут хранит свою ценность в глобальном (внешнем по отношению к атрибуту) хранилище, к которому можно получить доступ из любого значения атрибута. Значения атрибутов должны гарантировать, что их сохраненные значения не изменяются с течением времени и безопасно доступны одновременно из разных потоков.

В качестве специального случая для второго пункта можно хранить значения атрибутов (или их части) в нитевидном хранилище. Однако в этом случае пользователь должен правильно реализовать метод detach_from_thread реализации значения атрибута. Результат этого метода - другое значение атрибута - должен быть независимым от потока, в который он вызывается, но его сохраненное значение должно быть эквивалентно исходному значению атрибута. Этот метод будет называться библиотекой, когда значение атрибута переходит в поток, который отличается от потока, где он был создан. На данный момент это произойдет только в случае асинхронных рубок .

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

// The function returns the system uptime, in seconds
unsigned int get_uptime();
// Attribute implementation class
class system_uptime_impl :
    public logging::attribute::impl
{
public:
    // The method generates a new attribute value
    logging::attribute_value get_value()
    {
        return attrs::make_attribute_value(get_uptime());
    }
};

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

[Tip]Tip

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

Класс интерфейса атрибута можно определить следующим образом:

// Attribute interface class
class system_uptime :
    public logging::attribute
{
public:
    system_uptime() : logging::attribute(new system_uptime_impl())
    {
    }
    // Attribute casting support
    explicit system_uptime(attrs::cast_source const& source) : logging::attribute(source.as< system_uptime_impl >())
    {
    }
};

Как упоминалось ранее, конструктор по умолчанию создает экземпляр реализации так, чтобы построенный по умолчанию атрибут мог использоваться библиотекой.

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

Определив эти два класса, атрибут можно использовать с библиотекой как обычно:

void init_logging()
{
    boost::shared_ptr< logging::core > core = logging::core::get();
    // ...
    // Add the uptime attribute to the core
    core->add_global_attribute("SystemUptime", system_uptime());
}

См. полный код .


PrevUpHomeNext

Статья Writing your own attributes раздела Chapter 1. Boost.Log v2 Extending the library может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Extending the library ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 19:29:01/0.02754020690918/1