1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sp_debug.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
33 // MARKER(update_precomp.py): autogen include statement, do not remove
34 #include "precompiled_slideshow.hxx"
38 // Copyright (c) 2002, 2003 Peter Dimov
40 // Permission to copy, use, modify, sell and distribute this software
41 // is granted provided this copyright notice appears in all copies.
42 // This software is provided "as is" without express or implied
43 // warranty, and with no claim as to its suitability for any purpose.
46 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
48 #include <boost/assert.hpp>
49 #include <boost/shared_ptr.hpp>
50 #include <boost/detail/lightweight_mutex.hpp>
56 typedef std::map
< void const *, std::pair
<void *, size_t> > map_type
;
58 static map_type
& get_map()
64 typedef boost::detail::lightweight_mutex mutex_type
;
66 static mutex_type
& get_mutex()
72 static void * init_mutex_before_main
= &get_mutex();
80 boost::detail::sp_counted_base
* pi
;
84 struct shared_ptr_layout
91 // assume 4 byte alignment for pointers when scanning
92 size_t const pointer_align
= 4;
94 typedef std::map
<void const *, long> map2_type
;
96 static void scan_and_count(void const * area
, size_t size
, map_type
const & m
, map2_type
& m2
)
98 unsigned char const * p
= static_cast<unsigned char const *>(area
);
100 for(size_t n
= 0; n
+ sizeof(shared_ptr_layout
) <= size
; p
+= pointer_align
, n
+= pointer_align
)
102 shared_ptr_layout
const * q
= reinterpret_cast<shared_ptr_layout
const *>(p
);
104 if(q
->pn
.id
== boost::detail::shared_count_id
&& q
->pn
.pi
!= 0 && m
.count(q
->pn
.pi
) != 0)
111 typedef std::deque
<void const *> open_type
;
113 static void scan_and_mark(void const * area
, size_t size
, map2_type
& m2
, open_type
& open
)
115 unsigned char const * p
= static_cast<unsigned char const *>(area
);
117 for(size_t n
= 0; n
+ sizeof(shared_ptr_layout
) <= size
; p
+= pointer_align
, n
+= pointer_align
)
119 shared_ptr_layout
const * q
= reinterpret_cast<shared_ptr_layout
const *>(p
);
121 if(q
->pn
.id
== boost::detail::shared_count_id
&& q
->pn
.pi
!= 0 && m2
.count(q
->pn
.pi
) != 0)
123 open
.push_back(q
->pn
.pi
);
129 static void find_unreachable_objects_impl(map_type
const & m
, map2_type
& m2
)
131 // scan objects for shared_ptr members, compute internal counts
134 std::cout
<< "... " << m
.size() << " objects in m.\n";
136 for(map_type::const_iterator i
= m
.begin(); i
!= m
.end(); ++i
)
138 BOOST_ASSERT(static_cast<boost::detail::sp_counted_base
const *>(i
->first
)->use_count() != 0); // there should be no inactive counts in the map
140 scan_and_count(i
->second
.first
, i
->second
.second
, m
, m2
);
143 std::cout
<< "... " << m2
.size() << " objects in m2.\n";
146 // mark reachable objects
151 for(map2_type::iterator i
= m2
.begin(); i
!= m2
.end(); ++i
)
153 boost::detail::sp_counted_base
const * p
= static_cast<boost::detail::sp_counted_base
const *>(i
->first
);
154 if(p
->use_count() != i
->second
) open
.push_back(p
);
157 std::cout
<< "... " << m2
.size() << " objects in open.\n";
159 for(open_type::iterator j
= open
.begin(); j
!= open
.end(); ++j
)
166 void const * p
= open
.front();
169 map_type::const_iterator i
= m
.find(p
);
170 BOOST_ASSERT(i
!= m
.end());
172 scan_and_mark(i
->second
.first
, i
->second
.second
, m2
, open
);
176 // m2 now contains the unreachable objects
179 std::size_t find_unreachable_objects(bool report
)
183 #ifdef BOOST_HAS_THREADS
185 // This will work without the #ifdef, but some compilers warn
186 // that lock is not referenced
188 mutex_type::scoped_lock
lock(get_mutex());
192 map_type
const & m
= get_map();
194 find_unreachable_objects_impl(m
, m2
);
198 for(map2_type::iterator j
= m2
.begin(); j
!= m2
.end(); ++j
)
200 map_type::const_iterator i
= m
.find(j
->first
);
201 BOOST_ASSERT(i
!= m
.end());
202 std::cout
<< "Unreachable object at " << i
->second
.first
<< ", " << i
->second
.second
<< " bytes long.\n";
209 typedef std::deque
< boost::shared_ptr
<X
> > free_list_type
;
211 static void scan_and_free(void * area
, size_t size
, map2_type
const & m2
, free_list_type
& free
)
213 unsigned char * p
= static_cast<unsigned char *>(area
);
215 for(size_t n
= 0; n
+ sizeof(shared_ptr_layout
) <= size
; p
+= pointer_align
, n
+= pointer_align
)
217 shared_ptr_layout
* q
= reinterpret_cast<shared_ptr_layout
*>(p
);
219 if(q
->pn
.id
== boost::detail::shared_count_id
&& q
->pn
.pi
!= 0 && m2
.count(q
->pn
.pi
) != 0 && q
->px
!= 0)
221 boost::shared_ptr
<X
> * ppx
= reinterpret_cast< boost::shared_ptr
<X
> * >(p
);
222 free
.push_back(*ppx
);
228 void free_unreachable_objects()
235 #ifdef BOOST_HAS_THREADS
237 mutex_type::scoped_lock
lock(get_mutex());
241 map_type
const & m
= get_map();
243 find_unreachable_objects_impl(m
, m2
);
245 for(map2_type::iterator j
= m2
.begin(); j
!= m2
.end(); ++j
)
247 map_type::const_iterator i
= m
.find(j
->first
);
248 BOOST_ASSERT(i
!= m
.end());
249 scan_and_free(i
->second
.first
, i
->second
.second
, m2
, free
);
253 std::cout
<< "... about to free " << free
.size() << " objects.\n";
261 void sp_scalar_constructor_hook(void *)
265 void sp_scalar_constructor_hook(void * px
, std::size_t size
, void * pn
)
267 #ifdef BOOST_HAS_THREADS
269 mutex_type::scoped_lock
lock(get_mutex());
273 get_map()[pn
] = std::make_pair(px
, size
);
276 void sp_scalar_destructor_hook(void *)
280 void sp_scalar_destructor_hook(void *, std::size_t, void * pn
)
282 #ifdef BOOST_HAS_THREADS
284 mutex_type::scoped_lock
lock(get_mutex());
291 void sp_array_constructor_hook(void *)
295 void sp_array_destructor_hook(void *)
301 #endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)