named_scope.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2013.
  3. * Distributed under the Boost Software License, Version 1.0.
  4. * (See accompanying file LICENSE_1_0.txt or copy at
  5. * http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. /*!
  8. * \file
  9. * \author Andrey Semashev
  10. * \date 24.06.2007
  11. *
  12. * The header contains implementation of named scope container and an attribute that allows to
  13. * put the named scope to log. A number of convenience macros are also provided.
  14. */
  15. #ifndef BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_
  16. #define BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_
  17. #include <ostream>
  18. #include <memory>
  19. #include <iterator>
  20. #include <cstddef>
  21. #include <boost/log/detail/config.hpp>
  22. #include <boost/current_function.hpp>
  23. #include <boost/mpl/if.hpp>
  24. #include <boost/log/utility/string_literal.hpp>
  25. #include <boost/log/utility/unique_identifier_name.hpp>
  26. #include <boost/log/utility/unused_variable.hpp>
  27. #include <boost/log/attributes/attribute.hpp>
  28. #include <boost/log/attributes/attribute_cast.hpp>
  29. #include <boost/log/detail/header.hpp>
  30. #ifdef BOOST_HAS_PRAGMA_ONCE
  31. #pragma once
  32. #endif
  33. namespace boost {
  34. BOOST_LOG_OPEN_NAMESPACE
  35. namespace attributes {
  36. namespace aux {
  37. //! Double-linked list node
  38. struct named_scope_list_node
  39. {
  40. mutable named_scope_list_node* _m_pPrev;
  41. mutable named_scope_list_node* _m_pNext;
  42. named_scope_list_node() BOOST_NOEXCEPT { _m_pPrev = _m_pNext = this; }
  43. };
  44. } // namespace aux
  45. /*!
  46. * \brief The structure contains all information about a named scope
  47. *
  48. * The named scope entries are stored as elements of \c basic_named_scope_list container, which
  49. * in turn can be acquired either from the \c basic_named_scope attribute value or from a thread-local
  50. * instance.
  51. */
  52. struct named_scope_entry
  53. //! \cond
  54. : public aux::named_scope_list_node
  55. //! \endcond
  56. {
  57. /*!
  58. * The scope name (e.g. a function signature)
  59. */
  60. string_literal scope_name;
  61. /*!
  62. * The source file name
  63. */
  64. string_literal file_name;
  65. /*!
  66. * The line number in the source file
  67. */
  68. unsigned int line;
  69. /*!
  70. * Initializing constructor
  71. *
  72. * \post <tt>scope_name == sn && file_name == fn && line == ln</tt>
  73. *
  74. * \b Throws: Nothing.
  75. */
  76. named_scope_entry(string_literal const& sn, string_literal const& fn, unsigned int ln) BOOST_NOEXCEPT :
  77. scope_name(sn),
  78. file_name(fn),
  79. line(ln)
  80. {
  81. }
  82. };
  83. /*!
  84. * \brief The class implements the list of scopes
  85. *
  86. * The scope list provides a read-only access to a doubly-linked list of scopes.
  87. */
  88. class named_scope_list
  89. //! \cond
  90. : protected std::allocator< named_scope_entry >
  91. //! \endcond
  92. {
  93. public:
  94. //! Allocator type
  95. typedef std::allocator< named_scope_entry > allocator_type;
  96. // Standard types
  97. typedef allocator_type::value_type value_type;
  98. typedef allocator_type::reference reference;
  99. typedef allocator_type::const_reference const_reference;
  100. typedef allocator_type::pointer pointer;
  101. typedef allocator_type::const_pointer const_pointer;
  102. typedef allocator_type::size_type size_type;
  103. typedef allocator_type::difference_type difference_type;
  104. #ifndef BOOST_LOG_DOXYGEN_PASS
  105. protected:
  106. //! Iterator class
  107. #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS
  108. template< bool fConstV > class iter;
  109. template< bool fConstV > friend class iter;
  110. #endif
  111. template< bool fConstV >
  112. class iter
  113. {
  114. friend class iter< !fConstV >;
  115. public:
  116. // Standard typedefs
  117. typedef named_scope_list::difference_type difference_type;
  118. typedef named_scope_list::value_type value_type;
  119. typedef typename mpl::if_c<
  120. fConstV,
  121. named_scope_list::const_reference,
  122. named_scope_list::reference
  123. >::type reference;
  124. typedef typename mpl::if_c<
  125. fConstV,
  126. named_scope_list::const_pointer,
  127. named_scope_list::pointer
  128. >::type pointer;
  129. typedef std::bidirectional_iterator_tag iterator_category;
  130. public:
  131. // Constructors
  132. iter() : m_pNode(NULL) {}
  133. explicit iter(aux::named_scope_list_node* pNode) : m_pNode(pNode) {}
  134. iter(iter< false > const& that) : m_pNode(that.m_pNode) {}
  135. //! Assignment
  136. template< bool f >
  137. iter& operator= (iter< f > const& that)
  138. {
  139. m_pNode = that.m_pNode;
  140. return *this;
  141. }
  142. // Comparison
  143. template< bool f >
  144. bool operator== (iter< f > const& that) const { return (m_pNode == that.m_pNode); }
  145. template< bool f >
  146. bool operator!= (iter< f > const& that) const { return (m_pNode != that.m_pNode); }
  147. // Modification
  148. iter& operator++ ()
  149. {
  150. m_pNode = m_pNode->_m_pNext;
  151. return *this;
  152. }
  153. iter& operator-- ()
  154. {
  155. m_pNode = m_pNode->_m_pPrev;
  156. return *this;
  157. }
  158. iter operator++ (int)
  159. {
  160. iter tmp(*this);
  161. m_pNode = m_pNode->_m_pNext;
  162. return tmp;
  163. }
  164. iter operator-- (int)
  165. {
  166. iter tmp(*this);
  167. m_pNode = m_pNode->_m_pPrev;
  168. return tmp;
  169. }
  170. // Dereferencing
  171. pointer operator-> () const { return static_cast< pointer >(m_pNode); }
  172. reference operator* () const { return *static_cast< pointer >(m_pNode); }
  173. private:
  174. aux::named_scope_list_node* m_pNode;
  175. };
  176. public:
  177. typedef iter< true > const_iterator;
  178. typedef iter< false > iterator;
  179. typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
  180. typedef std::reverse_iterator< iterator > reverse_iterator;
  181. protected:
  182. //! The root node of the container
  183. aux::named_scope_list_node m_RootNode;
  184. //! The size of the container
  185. size_type m_Size;
  186. //! The flag shows if the contained elements are dynamically allocated
  187. bool m_fNeedToDeallocate;
  188. #else // BOOST_LOG_DOXYGEN_PASS
  189. /*!
  190. * A constant iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
  191. */
  192. typedef implementation_defined const_iterator;
  193. /*!
  194. * An iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
  195. */
  196. typedef implementation_defined iterator;
  197. /*!
  198. * A constant reverse iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
  199. */
  200. typedef implementation_defined const_reverse_iterator;
  201. /*!
  202. * A reverse iterator to the sequence of scopes. Complies to bidirectional iterator requirements.
  203. */
  204. typedef implementation_defined reverse_iterator;
  205. #endif // BOOST_LOG_DOXYGEN_PASS
  206. public:
  207. /*!
  208. * Default constructor
  209. *
  210. * \post <tt>empty() == true</tt>
  211. */
  212. named_scope_list() : m_Size(0), m_fNeedToDeallocate(false) {}
  213. /*!
  214. * Copy constructor
  215. *
  216. * \post <tt>std::equal(begin(), end(), that.begin()) == true</tt>
  217. */
  218. BOOST_LOG_API named_scope_list(named_scope_list const& that);
  219. /*!
  220. * Destructor. Destroys the stored entries.
  221. */
  222. BOOST_LOG_API ~named_scope_list();
  223. /*!
  224. * Assignment operator
  225. *
  226. * \post <tt>std::equal(begin(), end(), that.begin()) == true</tt>
  227. */
  228. named_scope_list& operator= (named_scope_list const& that)
  229. {
  230. if (this != &that)
  231. {
  232. named_scope_list tmp(that);
  233. swap(tmp);
  234. }
  235. return *this;
  236. }
  237. /*!
  238. * \return Constant iterator to the first element of the container.
  239. */
  240. const_iterator begin() const { return const_iterator(m_RootNode._m_pNext); }
  241. /*!
  242. * \return Constant iterator to the after-the-last element of the container.
  243. */
  244. const_iterator end() const { return const_iterator(const_cast< aux::named_scope_list_node* >(&m_RootNode)); }
  245. /*!
  246. * \return Constant iterator to the last element of the container.
  247. */
  248. const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
  249. /*!
  250. * \return Constant iterator to the before-the-first element of the container.
  251. */
  252. const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
  253. /*!
  254. * \return The number of elements in the container
  255. */
  256. size_type size() const { return m_Size; }
  257. /*!
  258. * \return true if the container is empty and false otherwise
  259. */
  260. bool empty() const { return (m_Size == 0); }
  261. /*!
  262. * Swaps two instances of the container
  263. */
  264. BOOST_LOG_API void swap(named_scope_list& that);
  265. /*!
  266. * \return Last pushed scope entry
  267. */
  268. const_reference back() const { return *rbegin(); }
  269. /*!
  270. * \return First pushed scope entry
  271. */
  272. const_reference front() const { return *begin(); }
  273. };
  274. //! Stream output operator
  275. template< typename CharT, typename TraitsT >
  276. inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, named_scope_list const& sl)
  277. {
  278. if (strm.good())
  279. {
  280. named_scope_list::const_iterator it = sl.begin(), end = sl.end();
  281. if (it != end)
  282. {
  283. strm << it->scope_name.c_str();
  284. for (++it; it != end; ++it)
  285. strm << "->" << it->scope_name.c_str();
  286. }
  287. }
  288. return strm;
  289. }
  290. /*!
  291. * \brief A class of an attribute that holds stack of named scopes of the current thread
  292. *
  293. * The basic_named_scope attribute is essentially a hook to the thread-specific instance of
  294. * scope list. This means that the attribute will generate different values if get_value is
  295. * called in different threads. The attribute generates value with stored type
  296. * <tt>basic_named_scope_list< CharT ></tt>.
  297. *
  298. * The attribute class can also be used to gain access to the scope stack instance, e.g. to
  299. * get its copy or to push or pop a scope entry. However, it is highly not recommended to
  300. * maintain scope list manually. Use \c BOOST_LOG_NAMED_SCOPE or \c BOOST_LOG_FUNCTION macros instead.
  301. */
  302. class BOOST_LOG_API named_scope :
  303. public attribute
  304. {
  305. public:
  306. //! Scope names stack (the attribute value type)
  307. typedef named_scope_list value_type;
  308. //! Scope entry
  309. typedef value_type::value_type scope_entry;
  310. //! Sentry object class to automatically push and pop scopes
  311. struct sentry
  312. {
  313. /*!
  314. * Constructor. Pushes the specified scope to the end of the thread-local list of scopes.
  315. *
  316. * \param sn Scope name.
  317. * \param fn File name, in which the scope is located.
  318. * \param ln Line number in the file.
  319. */
  320. sentry(string_literal const& sn, string_literal const& fn, unsigned int ln) BOOST_NOEXCEPT :
  321. m_Entry(sn, fn, ln)
  322. {
  323. named_scope::push_scope(m_Entry);
  324. }
  325. /*!
  326. * Destructor. Removes the last pushed scope from the thread-local list of scopes.
  327. */
  328. ~sentry() BOOST_NOEXCEPT
  329. {
  330. named_scope::pop_scope();
  331. }
  332. BOOST_DELETED_FUNCTION(sentry(sentry const&))
  333. BOOST_DELETED_FUNCTION(sentry& operator= (sentry const&))
  334. private:
  335. scope_entry m_Entry;
  336. };
  337. private:
  338. //! Attribute implementation class
  339. struct BOOST_SYMBOL_VISIBLE impl;
  340. public:
  341. /*!
  342. * Constructor. Creates an attribute.
  343. */
  344. named_scope();
  345. /*!
  346. * Constructor for casting support
  347. */
  348. explicit named_scope(cast_source const& source);
  349. /*!
  350. * The method pushes the scope to the back of the current thread's scope list
  351. *
  352. * \b Throws: Nothing.
  353. */
  354. static void push_scope(scope_entry const& entry) BOOST_NOEXCEPT;
  355. /*!
  356. * The method pops the last pushed scope from the current thread's scope list
  357. *
  358. * \b Throws: Nothing.
  359. */
  360. static void pop_scope() BOOST_NOEXCEPT;
  361. /*!
  362. * \return The current thread's list of scopes
  363. *
  364. * \note The returned reference is only valid until the current thread ends. The scopes in the
  365. * returned container may change if the execution scope is changed (i.e. either \c push_scope
  366. * or \c pop_scope is called). User has to copy the stack if he wants to keep it intact regardless
  367. * of the execution scope.
  368. */
  369. static value_type const& get_scopes();
  370. };
  371. } // namespace attributes
  372. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  373. } // namespace boost
  374. #ifndef BOOST_LOG_DOXYGEN_PASS
  375. #define BOOST_LOG_NAMED_SCOPE_INTERNAL(var, name, file, line)\
  376. BOOST_LOG_UNUSED_VARIABLE(::boost::log::attributes::named_scope::sentry, var, (name, file, line));
  377. #endif // BOOST_LOG_DOXYGEN_PASS
  378. /*!
  379. * Macro for scope markup. The specified scope name is pushed to the end of the current thread scope list.
  380. */
  381. #define BOOST_LOG_NAMED_SCOPE(name)\
  382. BOOST_LOG_NAMED_SCOPE_INTERNAL(BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_named_scope_sentry_), name, __FILE__, __LINE__)
  383. /*!
  384. * Macro for function scope markup. The scope name is constructed with help of compiler and contains current function name.
  385. * The scope name is pushed to the end of the current thread scope list.
  386. *
  387. * Not all compilers have support for this macro. The exact form of the scope name may vary from one compiler to another.
  388. */
  389. #define BOOST_LOG_FUNCTION() BOOST_LOG_NAMED_SCOPE(BOOST_CURRENT_FUNCTION)
  390. #include <boost/log/detail/footer.hpp>
  391. #endif // BOOST_LOG_ATTRIBUTES_NAMED_SCOPE_HPP_INCLUDED_