named_scope.hpp 15 KB

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