Added support for hashing

This commit is contained in:
Antony Polukhin
2016-10-12 20:26:09 +03:00
parent 40d1fcba36
commit ab6cb7483e
11 changed files with 60 additions and 17 deletions

View File

@@ -86,6 +86,8 @@ class stacktrace {
boost::stacktrace::detail::backtrace_holder impl_;
#endif
std::size_t hash_code_;
public:
/// @brief Stores the current function call sequence inside the class.
///
@@ -136,6 +138,13 @@ public:
///
/// @b Complexity: Amortized O(1); worst case O(size())
BOOST_STACKTRACE_FUNCTION bool operator==(const stacktrace& rhs) const BOOST_NOEXCEPT;
/// @brief Returns hashed code of the stacktrace.
///
/// @b Complexity: O(1)
std::size_t hash_code() const BOOST_NOEXCEPT {
return hash_code_;
}
};
/// Additional comparison operators for stacktraces that have amortized O(1) complexity.
@@ -144,6 +153,11 @@ inline bool operator<=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXC
inline bool operator>=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs < rhs); }
inline bool operator!=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs == rhs); }
/// Hashing support
inline std::size_t hash_value(const stacktrace& st) BOOST_NOEXCEPT {
return st.hash_code();
}
/// Outputs stacktrace in a human readable format to output stream.
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const stacktrace& bt) {

View File

@@ -28,10 +28,6 @@ struct backtrace_holder {
std::size_t frames_count;
boost::shared_ptr<std::string[]> frames;
BOOST_FORCEINLINE backtrace_holder() BOOST_NOEXCEPT
: frames_count(0)
{}
inline std::size_t size() const BOOST_NOEXCEPT {
return frames_count;
}

View File

@@ -36,7 +36,6 @@ struct backtrace_holder {
return res;
}
Dl_info dli;
if (!!dladdr(buffer[frame], &dli) && dli.dli_sname) {
boost::core::scoped_demangled_name demangled(dli.dli_sname);

View File

@@ -23,7 +23,7 @@ struct backtrace_holder {
inline std::string get_frame(std::size_t /*frame*/) const {
return std::string();
}
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
return false;
}

View File

@@ -36,10 +36,12 @@ namespace boost { namespace stacktrace {
stacktrace::stacktrace(const stacktrace& bt) BOOST_NOEXCEPT
: impl_(bt.impl_)
, hash_code_(bt.hash_code_)
{}
stacktrace& stacktrace::operator=(const stacktrace& bt) BOOST_NOEXCEPT {
impl_ = bt.impl_;
hash_code_ = bt.hash_code_;
return *this;
}
@@ -54,11 +56,11 @@ std::string stacktrace::operator[](std::size_t frame) const {
}
bool stacktrace::operator< (const stacktrace& rhs) const BOOST_NOEXCEPT {
return impl_ < rhs.impl_;
return hash_code_ < rhs.hash_code_ || (hash_code_ == rhs.hash_code_ && impl_ < rhs.impl_);
}
bool stacktrace::operator==(const stacktrace& rhs) const BOOST_NOEXCEPT {
return impl_ == rhs.impl_;
return hash_code_ == rhs.hash_code_ && impl_ == rhs.impl_;
}
}}

View File

@@ -16,10 +16,15 @@
#include <boost/stacktrace/detail/backtrace_holder_libunwind.hpp>
#include <boost/stacktrace/detail/helpers.hpp>
#include <boost/functional/hash.hpp>
namespace boost { namespace stacktrace {
stacktrace::stacktrace() BOOST_NOEXCEPT {
stacktrace::stacktrace() BOOST_NOEXCEPT
: hash_code_(0)
{
boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_);
bt.frames_count = 0;
unw_context_t uc;
if (unw_getcontext(&uc) != 0) {
@@ -47,6 +52,7 @@ stacktrace::stacktrace() BOOST_NOEXCEPT {
std::size_t i = 0;
while (unw_step(&cursor) > 0){
bt.frames[i] = boost::stacktrace::detail::backtrace_holder::get_frame_impl(cursor);
boost::hash_combine(hash_code_, bt.frames[i]);
++ i;
}
} BOOST_CATCH(...) {}

View File

@@ -16,14 +16,20 @@
#include <boost/stacktrace/detail/backtrace_holder_linux.hpp>
#include <boost/stacktrace/detail/helpers.hpp>
#include <boost/functional/hash.hpp>
namespace boost { namespace stacktrace {
stacktrace::stacktrace() BOOST_NOEXCEPT {
stacktrace::stacktrace() BOOST_NOEXCEPT
: hash_code_(0)
{
boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_);
bt.frames_count = ::backtrace(bt.buffer, boost::stacktrace::detail::backtrace_holder::max_size);
if (bt.buffer[bt.frames_count] == 0) {
if (bt.buffer[bt.frames_count - 1] == 0) {
-- bt.frames_count;
}
hash_code_ = boost::hash_range(bt.buffer, bt.buffer + bt.frames_count);
}
}} // namespace boost::stacktrace

View File

@@ -18,7 +18,9 @@
namespace boost { namespace stacktrace {
stacktrace::stacktrace() BOOST_NOEXCEPT {
stacktrace::stacktrace() BOOST_NOEXCEPT
: hash_code_(0)
{
boost::stacktrace::detail::construct_bt_and_return(impl_);
}

View File

@@ -18,9 +18,13 @@
namespace boost { namespace stacktrace {
stacktrace::stacktrace() BOOST_NOEXCEPT {
stacktrace::stacktrace() BOOST_NOEXCEPT
: hash_code_(0)
{
boost::stacktrace::detail::backtrace_holder& bt = boost::stacktrace::detail::construct_bt_and_return(impl_);
bt.frames_count = CaptureStackBackTrace(0, boost::stacktrace::detail::backtrace_holder::max_size, bt.buffer, 0);
boost::detail::winapi::ULONG_ hc = 0;
bt.frames_count = CaptureStackBackTrace(0, boost::stacktrace::detail::backtrace_holder::max_size, bt.buffer, &hc);
boost::hash_combine(hash_code_, hc);
}
}} // namespace boost::stacktrace