1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
24 // Copyright (c) 2002, 2003 Peter Dimov
26 // Permission to copy, use, modify, sell and distribute this software
27 // is granted provided this copyright notice appears in all copies.
28 // This software is provided "as is" without express or implied
29 // warranty, and with no claim as to its suitability for any purpose.
32 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
34 #include <boost/assert.hpp>
35 #include <boost/scoped_array.hpp>
36 #include <boost/scoped_ptr.hpp>
37 #include <boost/shared_ptr.hpp>
38 #include <boost/detail/lightweight_mutex.hpp>
39 #include <canvas/debug.hxx>
45 typedef std::map
< void const *, std::pair
<void *, size_t> > map_type
;
47 static map_type
& get_map()
53 typedef boost::detail::lightweight_mutex mutex_type
;
55 static mutex_type
& get_mutex()
61 static void * init_mutex_before_main
= &get_mutex();
69 boost::detail::sp_counted_base
* pi
;
73 struct shared_ptr_layout
80 // assume 4 byte alignment for pointers when scanning
81 size_t const pointer_align
= 4;
83 typedef std::map
<void const *, long> map2_type
;
85 static void scan_and_count(void const * area
, size_t size
, map_type
const & m
, map2_type
& m2
)
87 unsigned char const * p
= static_cast<unsigned char const *>(area
);
89 for(size_t n
= 0; n
+ sizeof(shared_ptr_layout
) <= size
; p
+= pointer_align
, n
+= pointer_align
)
91 shared_ptr_layout
const * q
= reinterpret_cast<shared_ptr_layout
const *>(p
);
93 if(q
->pn
.id
== boost::detail::shared_count_id
&& q
->pn
.pi
!= 0 && m
.count(q
->pn
.pi
) != 0)
100 typedef std::deque
<void const *> open_type
;
102 static void scan_and_mark(void const * area
, size_t size
, map2_type
& m2
, open_type
& open
)
104 unsigned char const * p
= static_cast<unsigned char const *>(area
);
106 for(size_t n
= 0; n
+ sizeof(shared_ptr_layout
) <= size
; p
+= pointer_align
, n
+= pointer_align
)
108 shared_ptr_layout
const * q
= reinterpret_cast<shared_ptr_layout
const *>(p
);
110 if(q
->pn
.id
== boost::detail::shared_count_id
&& q
->pn
.pi
!= 0 && m2
.count(q
->pn
.pi
) != 0)
112 open
.push_back(q
->pn
.pi
);
118 static void find_unreachable_objects_impl(map_type
const & m
, map2_type
& m2
)
120 // scan objects for shared_ptr members, compute internal counts
123 std::cout
<< "... " << m
.size() << " objects in m.\n";
125 for(map_type::const_iterator i
= m
.begin(); i
!= m
.end(); ++i
)
127 BOOST_ASSERT(static_cast<boost::detail::sp_counted_base
const *>(i
->first
)->use_count() != 0); // there should be no inactive counts in the map
129 scan_and_count(i
->second
.first
, i
->second
.second
, m
, m2
);
132 std::cout
<< "... " << m2
.size() << " objects in m2.\n";
135 // mark reachable objects
140 for(map2_type::iterator i
= m2
.begin(); i
!= m2
.end(); ++i
)
142 boost::detail::sp_counted_base
const * p
= static_cast<boost::detail::sp_counted_base
const *>(i
->first
);
143 if(p
->use_count() != i
->second
) open
.push_back(p
);
146 std::cout
<< "... " << m2
.size() << " objects in open.\n";
148 for(open_type::iterator j
= open
.begin(); j
!= open
.end(); ++j
)
155 void const * p
= open
.front();
158 map_type::const_iterator i
= m
.find(p
);
159 BOOST_ASSERT(i
!= m
.end());
161 scan_and_mark(i
->second
.first
, i
->second
.second
, m2
, open
);
165 // m2 now contains the unreachable objects
168 std::size_t find_unreachable_objects(bool report
)
172 #ifdef BOOST_HAS_THREADS
174 // This will work without the #ifdef, but some compilers warn
175 // that lock is not referenced
177 mutex_type::scoped_lock
lock(get_mutex());
181 map_type
const & m
= get_map();
183 find_unreachable_objects_impl(m
, m2
);
187 for(map2_type::iterator j
= m2
.begin(); j
!= m2
.end(); ++j
)
189 map_type::const_iterator i
= m
.find(j
->first
);
190 BOOST_ASSERT(i
!= m
.end());
191 std::cout
<< "Unreachable object at " << i
->second
.first
<< ", " << i
->second
.second
<< " bytes long.\n";
203 void sp_scalar_constructor_hook(void *)
207 void sp_scalar_constructor_hook(void * px
, std::size_t size
, void * pn
)
209 #ifdef BOOST_HAS_THREADS
211 mutex_type::scoped_lock
lock(get_mutex());
215 get_map()[pn
] = std::make_pair(px
, size
);
218 void sp_scalar_destructor_hook(void *)
222 void sp_scalar_destructor_hook(void *, std::size_t, void * pn
)
224 #ifdef BOOST_HAS_THREADS
226 mutex_type::scoped_lock
lock(get_mutex());
233 void sp_array_constructor_hook(void *)
237 void sp_array_destructor_hook(void *)
243 #endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */