• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Writing your own attributes</title>
5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../../index.html" title="Chapter 1. Boost.Log v2">
8<link rel="up" href="../extension.html" title="Extending the library">
9<link rel="prev" href="sources.html" title="Writing your own sources">
10<link rel="next" href="settings.html" title="Extending library settings support">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td></tr></table>
14<hr>
15<div class="spirit-nav">
16<a accesskey="p" href="sources.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../extension.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="settings.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
17</div>
18<div class="section">
19<div class="titlepage"><div><div><h3 class="title">
20<a name="log.extension.attributes"></a><a class="link" href="attributes.html" title="Writing your own attributes">Writing your own attributes</a>
21</h3></div></div></div>
22<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><code class="computeroutput"><a class="link" href="../../attributes.html#header.boost.log.attributes.attribute_hpp" title="Header &lt;boost/log/attributes/attribute.hpp&gt;">boost/log/attributes/attribute.hpp</a></code><span class="special">&gt;</span>
23<span class="preprocessor">#include</span> <span class="special">&lt;</span><code class="computeroutput"><a class="link" href="../../attributes.html#header.boost.log.attributes.attribute_value_hpp" title="Header &lt;boost/log/attributes/attribute_value.hpp&gt;">boost/log/attributes/attribute_value.hpp</a></code><span class="special">&gt;</span>
24<span class="preprocessor">#include</span> <span class="special">&lt;</span><code class="computeroutput"><a class="link" href="../../attributes.html#header.boost.log.attributes.attribute_value_impl_hpp" title="Header &lt;boost/log/attributes/attribute_value_impl.hpp&gt;">boost/log/attributes/attribute_value_impl.hpp</a></code><span class="special">&gt;</span>
25</pre>
26<p>
27        Developing your own attributes is quite simple. Generally, you need to do
28        the following:
29      </p>
30<div class="orderedlist"><ol class="orderedlist" type="1">
31<li class="listitem">
32            Define what will be the attribute value. Most likely, it will be a piece
33            of constant data that you want to participate in filtering and formatting.
34            Envelop this data into a class that derives from the <code class="computeroutput"><a class="link" href="../../boost/log/attribute_value/impl.html" title="Struct impl">impl</a></code>
35            interface; this is the attribute value implementation class. This object
36            will have to implement the <code class="computeroutput"><span class="identifier">dispatch</span></code>
37            method that will extract the stored data (or, in other words, the stored
38            value) to a type dispatcher. In most cases the class <code class="computeroutput"><a class="link" href="../../boost/log/attributes/attribute_value_impl.html" title="Class template attribute_value_impl">attribute_value_impl</a></code>
39            provided by the library can be used for this.
40          </li>
41<li class="listitem">
42            Use the <code class="computeroutput"><a class="link" href="../../boost/log/attribute_value.html" title="Class attribute_value">attribute_value</a></code>
43            class as the interface class that holds a reference to the attribute
44            value implementation.
45          </li>
46<li class="listitem">
47            Define how attribute values are going to be produced. In a corner case
48            the values do not need to be produced (like in the case of the <code class="computeroutput"><a class="link" href="../../boost/log/attributes/constant.html" title="Class template constant">constant</a></code> attribute
49            provided by the library), but often there is some logic that needs to
50            be invoked to acquire the attribute value. This logic has to be concentrated
51            in a class derived from the <code class="computeroutput"><a class="link" href="../../boost/log/attribute/impl.html" title="Struct impl">impl</a></code>
52            interface, more precisely - in the <code class="computeroutput"><span class="identifier">get_value</span></code>
53            method. This class is the attribute implementation class. You can think
54            of it as an attribute value factory.
55          </li>
56<li class="listitem">
57            Define the attribute interface class that derives from <code class="computeroutput"><a class="link" href="../../boost/log/attribute.html" title="Class attribute">attribute</a></code>.
58            By convention, the interface class should create the corresponding implementation
59            on construction and pass the pointer to it to the <code class="computeroutput"><a class="link" href="../../boost/log/attribute.html" title="Class attribute">attribute</a></code>
60            class constructor. The interface class may have interface methods but
61            it typically should not contain any data members as the data will be
62            lost when the attribute is added to the library. All relevant data should
63            be placed in the implementation class instead.
64          </li>
65</ol></div>
66<p>
67        While designing an attribute, one has to strive to make it as independent
68        from the values it produces, as possible. The attribute can be called from
69        different threads concurrently to produce a value. Once produced, the attribute
70        value can be used several times by the library (maybe even concurrently),
71        it can outlive the attribute object that created it, and several attribute
72        values produced by the same attribute can exist simultaneously.
73      </p>
74<p>
75        From the library perspective, each attribute value is considered independent
76        from other attribute values or the attribute itself. That said, it is still
77        possible to implement attributes that are also attribute values, which allows
78        to optimize performance in some cases. This is possible if the following
79        requirements are fulfilled:
80      </p>
81<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
82<li class="listitem">
83            The attribute value never changes, so it's possible to store it in the
84            attribute itself. The <code class="computeroutput"><a class="link" href="../../boost/log/attributes/constant.html" title="Class template constant">constant</a></code>
85            attribute is an example.
86          </li>
87<li class="listitem">
88            The attribute stores its value in a global (external with regard to the
89            attribute) storage, that can be accessed from any attribute value. The
90            attribute values must guarantee, though, that their stored values do
91            not change over time and are safely accessible concurrently from different
92            threads.
93          </li>
94</ul></div>
95<p>
96        As a special case for the second point, it is possible to store attribute
97        values (or their parts) in a thread-specific storage. However, in that case
98        the user has to implement the <code class="computeroutput"><span class="identifier">detach_from_thread</span></code>
99        method of the attribute value implementation properly. The result of this
100        method - another attribute value - must be independent from the thread it
101        is being called in, but its stored value should be equivalent to the original
102        attribute value. This method will be called by the library when the attribute
103        value passes to a thread that is different from the thread where it was created.
104        As of this moment, this will only happen in the case of <a class="link" href="../detailed/sink_frontends.html#log.detailed.sink_frontends.async" title="Asynchronous sink frontend">asynchronous
105        logging sinks</a>.
106      </p>
107<p>
108        But in the vast majority of cases attribute values must be self-contained
109        objects with no dependencies on other entities. In fact, this case is so
110        common that the library provides a ready to use attribute value implementation
111        class template <code class="computeroutput"><a class="link" href="../../boost/log/attributes/attribute_value_impl.html" title="Class template attribute_value_impl">attribute_value_impl</a></code>
112        and <code class="computeroutput"><a class="link" href="../../boost/log/attributes/make_attribute_value.html" title="Function template make_attribute_value">make_attribute_value</a></code>
113        generator function. The class template has to be instantiated on the stored
114        value type, and the stored value has to be provided to the class constructor.
115        For example, let's implement an attribute that returns system uptime in seconds.
116        This is the attribute implementation class.
117      </p>
118<p>
119</p>
120<pre class="programlisting"><span class="comment">// The function returns the system uptime, in seconds</span>
121<span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">get_uptime</span><span class="special">();</span>
122
123<span class="comment">// Attribute implementation class</span>
124<span class="keyword">class</span> <span class="identifier">system_uptime_impl</span> <span class="special">:</span>
125    <span class="keyword">public</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute</span><span class="special">::</span><span class="identifier">impl</span>
126<span class="special">{</span>
127<span class="keyword">public</span><span class="special">:</span>
128    <span class="comment">// The method generates a new attribute value</span>
129    <span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute_value</span> <span class="identifier">get_value</span><span class="special">()</span>
130    <span class="special">{</span>
131        <span class="keyword">return</span> <span class="identifier">attrs</span><span class="special">::</span><span class="identifier">make_attribute_value</span><span class="special">(</span><span class="identifier">get_uptime</span><span class="special">());</span>
132    <span class="special">}</span>
133<span class="special">};</span>
134</pre>
135<p>
136      </p>
137<p>
138        Since there is no need for special attribute value classes we can use the
139        <code class="computeroutput"><a class="link" href="../../boost/log/attributes/make_attribute_value.html" title="Function template make_attribute_value">make_attribute_value</a></code>
140        function to create the value envelop.
141      </p>
142<div class="tip"><table border="0" summary="Tip">
143<tr>
144<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
145<th align="left">Tip</th>
146</tr>
147<tr><td align="left" valign="top"><p>
148          For cases like this, when the attribute value can be obtained in a single
149          function call, it is typically more convenient to use the <a class="link" href="../detailed/attributes.html#log.detailed.attributes.function" title="Function objects as attributes"><code class="computeroutput"><span class="identifier">function</span></code></a> attribute.
150        </p></td></tr>
151</table></div>
152<p>
153        The interface class of the attribute can be defined as follows:
154      </p>
155<p>
156</p>
157<pre class="programlisting"><span class="comment">// Attribute interface class</span>
158<span class="keyword">class</span> <span class="identifier">system_uptime</span> <span class="special">:</span>
159    <span class="keyword">public</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute</span>
160<span class="special">{</span>
161<span class="keyword">public</span><span class="special">:</span>
162    <span class="identifier">system_uptime</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute</span><span class="special">(</span><span class="keyword">new</span> <span class="identifier">system_uptime_impl</span><span class="special">())</span>
163    <span class="special">{</span>
164    <span class="special">}</span>
165    <span class="comment">// Attribute casting support</span>
166    <span class="keyword">explicit</span> <span class="identifier">system_uptime</span><span class="special">(</span><span class="identifier">attrs</span><span class="special">::</span><span class="identifier">cast_source</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">source</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">attribute</span><span class="special">(</span><span class="identifier">source</span><span class="special">.</span><span class="identifier">as</span><span class="special">&lt;</span> <span class="identifier">system_uptime_impl</span> <span class="special">&gt;())</span>
167    <span class="special">{</span>
168    <span class="special">}</span>
169<span class="special">};</span>
170</pre>
171<p>
172      </p>
173<p>
174        As it was mentioned before, the default constructor creates the implementation
175        instance so that the default constructed attribute can be used by the library.
176      </p>
177<p>
178        The second constructor adds support for <a class="link" href="../detailed/attributes.html" title="Attributes">attribute
179        casting</a>. The constructor argument contains a reference to an attribute
180        implementation object, and by calling <code class="computeroutput"><span class="identifier">as</span></code>
181        on it the constructor attempts to upcast it to the implementation object
182        of our custom attribute. The <code class="computeroutput"><span class="identifier">as</span></code>
183        method will return <code class="computeroutput"><span class="identifier">NULL</span></code> if
184        the upcast fails, which will result in an empty attribute constructed in
185        case of failure.
186      </p>
187<p>
188        Having defined these two classes, the attribute can be used with the library
189        as usual:
190      </p>
191<p>
192</p>
193<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">init_logging</span><span class="special">()</span>
194<span class="special">{</span>
195    <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">core</span> <span class="special">&gt;</span> <span class="identifier">core</span> <span class="special">=</span> <span class="identifier">logging</span><span class="special">::</span><span class="identifier">core</span><span class="special">::</span><span class="identifier">get</span><span class="special">();</span>
196
197    <span class="comment">// ...</span>
198
199    <span class="comment">// Add the uptime attribute to the core</span>
200    <span class="identifier">core</span><span class="special">-&gt;</span><span class="identifier">add_global_attribute</span><span class="special">(</span><span class="string">"SystemUptime"</span><span class="special">,</span> <span class="identifier">system_uptime</span><span class="special">());</span>
201<span class="special">}</span>
202</pre>
203<p>
204      </p>
205<p>
206        <a href="../../../../../../libs/log/example/doc/extension_system_uptime_attr.cpp" target="_top">See
207        the complete code</a>.
208      </p>
209</div>
210<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
211<td align="left"></td>
212<td align="right"><div class="copyright-footer">Copyright © 2007-2019 Andrey Semashev<p>
213        Distributed under the Boost Software License, Version 1.0. (See accompanying
214        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>).
215      </p>
216</div></td>
217</tr></table>
218<hr>
219<div class="spirit-nav">
220<a accesskey="p" href="sources.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../extension.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="settings.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
221</div>
222</body>
223</html>
224