2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
21 * @brief implementation of tracing functionality.
23 * @copyright © Copyright 2008,2011 by Intra2net AG
25 * Every thread gets its' own ScopeTracker stack via TLS (thread local storage)
29 #include "tracefunc.hpp"
34 #include <boost/thread/tss.hpp>
41 using Logger::GlobalLogger;
43 class PerThreadContainer
46 typedef std::vector< ScopeTracker* > ScopeTrackerList;
48 /// List of currently active scope trackers
49 ScopeTrackerList scope_tracker_list;
51 /// Precomputed indent levels
52 std::vector< std::string > indents;
58 /// Internal TLS (thread local storage) data container
59 boost::thread_specific_ptr<PerThreadContainer> thread_container;
62 * Helper function to retrieve TLS pointer.
63 * Initializes the pointer if called for the first time.
64 * @return Pointer to the per thread container
66 static PerThreadContainer *TLS_get_container()
68 // First call? Construct options container
69 if (thread_container.get() == NULL)
70 thread_container.reset(new PerThreadContainer());
72 PerThreadContainer *per_thread = thread_container.get();
78 * @brief ensures indent level string to exist up to the desired level.
79 * @param level the desired indent level.
81 static void ensure_indent_level(PerThreadContainer *per_thread, int level)
83 // First initialization?
84 if (per_thread->indents.empty())
86 per_thread->indents.reserve(10);
90 per_thread->indents.push_back("");
93 while (per_thread->indents.size() <= level)
95 per_thread->indents.push_back( per_thread->indents.back() + " " );
97 } // eo ensure_indent_level(int)
99 } // eo namespace <anonymous>
103 ** implementation of ScopeTracker
107 * @brief constructor. initializes object with a source location and emits a ENTER message.
108 * @param loc the source location.
110 * the message is indented according to the current depth of nested ScopeTracker instances.
112 ScopeTracker::ScopeTracker(
113 const SourceLocation& loc)
117 , PerThread(TLS_get_container())
119 if (!PerThread->scope_tracker_list.empty())
121 ScopeTracker* last_tracker= PerThread->scope_tracker_list.back();
124 if (last_tracker->Location
125 && last_tracker->Location.File == Location.File
126 && last_tracker->Location.FunctionName == Location.FunctionName)
128 FuncDepth= last_tracker->FuncDepth+1;
131 Depth= last_tracker->Depth + 1;
133 ensure_indent_level(PerThread, Depth);
134 PerThread->scope_tracker_list.push_back(this);
136 std::ostringstream ostr;
137 if (Location.FunctionName.empty())
139 ostr << "<unknown> (global scope?)";
143 ostr << Location.FunctionName;
146 ostr << "#" << FuncDepth+1;
152 if (Logger::has_log_level(Logger::LogLevel::Debug))
154 GlobalLogger.debug() << PerThread->indents[Depth] << "ENTER " << Tag;
156 } // eo ScopeTrcaker::ScopeTracker(const SourceLocation&)
160 * @brief destructor. emits a LEAVE message.
164 ScopeTracker::~ScopeTracker()
167 if (Logger::has_log_level(Logger::LogLevel::Debug))
169 GlobalLogger.debug() << PerThread->indents[Depth] << "LEAVE " << Tag;
171 if (PerThread->scope_tracker_list.empty())
175 if (PerThread->scope_tracker_list.back() == this)
177 PerThread->scope_tracker_list.pop_back();
181 // oh hell, this should never be the case!
183 GlobalLogger.error() << "inconsistency detected in scope tracker";
185 } // eo ScopeTracker::~ScopeTracker()
190 } // eo namespace Tracer
191 } // eo namespace I2n