summaryrefslogtreecommitdiff
path: root/libs/log/src/timer.cpp
blob: c3f49518c4ea2c197f6d036db2487a48af413699 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 *          Copyright Andrey Semashev 2007 - 2014.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   timer.cpp
 * \author Andrey Semashev
 * \date   02.12.2007
 *
 * \brief  This header is the Boost.Log library implementation, see the library documentation
 *         at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
 */

#include <boost/config.hpp>
#include <boost/log/attributes/timer.hpp>
#include <boost/log/attributes/attribute_value_impl.hpp>

#if defined(BOOST_WINDOWS) && !defined(BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER)

#include "windows_version.hpp"
#include <boost/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/log/detail/config.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/detail/locks.hpp>
#include <boost/thread/mutex.hpp>
#endif
#include <windows.h>
#include <boost/log/detail/header.hpp>

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace attributes {

//! Factory implementation
class BOOST_SYMBOL_VISIBLE timer::impl :
    public attribute::impl
{
private:
#if !defined(BOOST_LOG_NO_THREADS)
    //! Synchronization mutex type
    typedef boost::mutex mutex_type;
    //! Synchronization mutex
    mutex_type m_Mutex;
#endif
    //! Frequency factor for calculating duration
    double m_FrequencyFactor;
    //! Last value of the performance counter
    uint64_t m_LastCounter;
    //! Elapsed time duration, in microseconds
    uint64_t m_Duration;

public:
    //! Constructor
    impl() : m_Duration(0)
    {
        LARGE_INTEGER li;
        QueryPerformanceFrequency(&li);
        BOOST_ASSERT(li.QuadPart != 0LL);
        m_FrequencyFactor = 1000000.0 / static_cast< double >(li.QuadPart);

        QueryPerformanceCounter(&li);
        m_LastCounter = static_cast< uint64_t >(li.QuadPart);
    }

    //! The method returns the actual attribute value. It must not return NULL.
    attribute_value get_value()
    {
        uint64_t duration;
        {
            BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)

            LARGE_INTEGER li;
            QueryPerformanceCounter(&li);
            const uint64_t counter = static_cast< uint64_t >(li.QuadPart);
            const uint64_t counts = counter - m_LastCounter;
            m_LastCounter = counter;
            duration = m_Duration + static_cast< uint64_t >(counts * m_FrequencyFactor);
            m_Duration = duration;
        }

        return attribute_value(new attribute_value_impl< value_type >(boost::posix_time::microseconds(duration)));
    }
};

//! Constructor
timer::timer() : attribute(new impl())
{
}

//! Constructor for casting support
timer::timer(cast_source const& source) : attribute(source.as< impl >())
{
}

} // namespace attributes

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#include <boost/log/detail/footer.hpp>

#else // defined(BOOST_WINDOWS) && !defined(BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER)

#include <boost/log/detail/header.hpp>

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace attributes {

//! Factory implementation
class BOOST_SYMBOL_VISIBLE timer::impl :
    public attribute::impl
{
public:
    //! Time type
    typedef utc_time_traits::time_type time_type;

private:
    //! Base time point
    const time_type m_BaseTimePoint;

public:
    /*!
     * Constructor. Starts time counting.
     */
    impl() : m_BaseTimePoint(utc_time_traits::get_clock()) {}

    attribute_value get_value()
    {
        return attribute_value(new attribute_value_impl< value_type >(
            utc_time_traits::get_clock() - m_BaseTimePoint));
    }
};

//! Constructor
timer::timer() : attribute(new impl())
{
}

//! Constructor for casting support
timer::timer(cast_source const& source) : attribute(source.as< impl >())
{
}

} // namespace attributes

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#include <boost/log/detail/footer.hpp>

#endif // defined(BOOST_WINDOWS) && !defined(BOOST_LOG_NO_QUERY_PERFORMANCE_COUNTER)