ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
dbgboxing.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10#if !defined(HPP_ALIB_BOXING_BOXING)
11# include "alib/boxing/boxing.hpp"
12#endif
13#endif // !defined(ALIB_DOX)
14
15#if ALIB_DEBUG_BOXING
16
17#if !defined(ALIB_DOX)
18# if !defined(HPP_ALIB_BOXING_DBGBOXING)
20# endif
21# if !defined(HPP_ALIB_COMPATIBILITY_STD_TYPEINFO)
23# endif
24
25# if ALIB_THREADS && !defined(HPP_ALIB_THREADS_THREADLOCK)
27# endif
28
29# if ALIB_CAMP
30# if !defined (HPP_ALIB_STRINGS_FORMAT)
32# endif
33# endif
34# if ALIB_MONOMEM
35# if !defined(HPP_ALIB_MONOMEM_HASHMAP)
37# endif
38# if !defined(HPP_ALIB_MONOMEM_HASHSET)
40# endif
41# else
42# if !defined(_GLIBCXX_UNORDERED_MAP) && !defined(_UNORDERED_MAP_)
43# include <unordered_map>
44# endif
45# if !defined(_GLIBCXX_UNORDERED_SET) && !defined(_UNORDERED_SET_)
46# include <unordered_set>
47# endif
48# endif
49
50#endif // !defined(ALIB_DOX)
51
52#if !defined (_GLIBCXX_ALGORITHM) && !defined(_ALGORITHM_)
53# include <algorithm>
54#endif
55
56namespace alib { namespace boxing { namespace detail {
57
58#if !defined(ALIB_DOX)
59
60#if ALIB_MONOMEM
61 extern HashSet <TypeFunctors::Key , TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownCustomFunctions;
62 HashSet <TypeFunctors::Key , TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownCustomFunctions(&monomem::GlobalAllocator);
63 extern HashMap <TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTables;
64 HashMap <TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTables(&monomem::GlobalAllocator);
65 extern HashMap <TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTablesArray;
66 HashMap <TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTablesArray(&monomem::GlobalAllocator);
67#else
68 extern std::unordered_set<TypeFunctors::Key , TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownCustomFunctions;
69 std::unordered_set<TypeFunctors::Key , TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownCustomFunctions;
70 extern std::unordered_map<TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTables;
71 std::unordered_map<TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTables;
72 extern std::unordered_map<TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTablesArray;
73 std::unordered_map<TypeFunctors::Key, detail::VTable*, TypeFunctors::Hash, TypeFunctors::EqualTo> DbgKnownVTablesArray;
74#endif
75
76
77 ALIB_IF_THREADS( namespace { ThreadLock dbgLock; } )
78
79 extern ALIB_API
80 void DbgLockMaps( bool doLock );
81 void DbgLockMaps( bool doLock )
82 {
83 #if !ALIB_THREADS
84 (void) doLock;
86 #else
87 if( doLock )
88 dbgLock.Acquire( ALIB_CALLER_PRUNED );
89 else
90 dbgLock.Release();
91 #endif
92 }
93
94#endif
95
97{
98 vtable->DbgProduction= productionType;
99 DbgLockMaps(true);
100 if( !vtable->IsArray() )
101 {
102 #if ALIB_MONOMEM
104 DbgKnownVTables.InsertUnique( std::make_pair( &vtable->Type, vtable ) );
105 #else
106 if ( DbgKnownVTables.find( &vtable->Type ) != DbgKnownVTables.end() )
107 {
108 ALIB_ERROR( "BOXING", "Double instantiation of VTable of Type: \"",
109 DbgTypeDemangler( vtable->Type ).Get(), "\"" )
110 DbgLockMaps(false);
111 return;
112 }
113
114 DbgKnownVTables.insert(std::make_pair( &vtable->Type, vtable ) );
115 #endif
116 }
117 else
118 {
119 #if ALIB_MONOMEM
121 DbgKnownVTablesArray.InsertUnique(std::make_pair( &vtable->ElementType, vtable ) );
122 #else
123 if ( DbgKnownVTablesArray.find( &vtable->ElementType ) != DbgKnownVTablesArray.end() )
124 {
125 ALIB_ERROR( "BOXING", "Double instantiation of VTable of Type: \"",
126 DbgTypeDemangler( vtable->ElementType ).Get(), "[]\"" )
127 DbgLockMaps(false);
128 return;
129 }
130
131 DbgKnownVTablesArray.insert(std::make_pair( &vtable->ElementType, vtable ) );
132 #endif
133 }
134 DbgLockMaps(false);
135}
136
137} // namespace alib::boxing[::detail]
138
139
140#if ALIB_STRINGS
141
142// #############################################################################################
143// Type Name
144// #############################################################################################
146{
147 for( auto& search: RemovableNamespaces )
148 {
149 integer idx;
150 while( (idx= string.IndexOf(search, startIndex) ) >= 0 )
151 string.Delete( idx, search.Length() );
152 }
153 return string;
154}
155
156std::vector<alib::String> DbgBoxing::RemovableNamespaces
157{
158 A_CHAR( "alib::boxing::" ),
159 A_CHAR( "alib::" ),
160};
161
162void DbgBoxing::typeName( const detail::VTable* vtable, AString& result )
163{
164 auto startLength= result.Length();
165 if( !vtable->IsArray() )
166 result << vtable->Type;
167 else
168 result << vtable->ElementType << "[]";
169
170 // MSC adds "class "
171 if( result.StartsWith( A_CHAR("class ") ) )
172 result.DeleteStart( 6 );
173
174 removeNamespaces(result, startLength);
175}
176
177#endif // ALIB_STRINGS
178
179#if ALIB_CAMP
180
181// #############################################################################################
182// Type Info
183// #############################################################################################
184
186 const detail::VTable* vtable,
187 const String& indent,
188 bool srcIsPointer,
189 bool isValueTypeCustomized,
190 bool isPointerTypeCustomized,
191 bool fitsToPlaceholder,
192 bool copyConstructible,
193 bool triviallyDestructible,
194 bool isUnboxable )
195{
196 target <<indent << "Mapping: " << ( vtable->Mapping == detail::VTable::MappingType::Pointer
197 ? "Pointer"
199 ? "Value"
201 ? "Enum"
202 : "Array"
203 ) << NewLine();
205 {
206 target << indent << "Mapped Type: "; typeName(vtable, target ); target << " (Enumeration)" << NewLine();
207 target << indent << "Customized: Not customizable (always boxed as enum value type)" << NewLine();
208 }
209 else
210 {
211 bool valueBoxing = vtable->Mapping == detail::VTable::MappingType::Value;
212 bool pointerBoxing= vtable->Mapping == detail::VTable::MappingType::Pointer;
213 bool arrayBoxing = vtable->IsArray();
214 bool srcIsValue = !srcIsPointer;
215
216 target << indent << "Mapped Type: "; typeName(vtable, target ); target << NewLine();
217
218 target <<indent << "Customized T: " << isValueTypeCustomized << NewLine();
219 target <<indent << "Customized T*: " << isPointerTypeCustomized << NewLine();
220 target <<indent << "Is Unboxable: "
221 <<( isUnboxable
222 ? ( srcIsValue && valueBoxing && isValueTypeCustomized
223 ? "Yes (By customization)"
224
225 : srcIsValue && valueBoxing && !isValueTypeCustomized
226 ? "Yes (Value fits in placeholder and is copy constructible)"
227
228 : srcIsPointer && pointerBoxing && isPointerTypeCustomized
229 ? "Yes (By customization)"
230
231 : srcIsPointer && pointerBoxing && !isPointerTypeCustomized && (!copyConstructible || !triviallyDestructible)
232 ? "Yes (Value would not be copy-constructible or trivially destructible)"
233
234 : srcIsPointer && pointerBoxing && !isPointerTypeCustomized && !fitsToPlaceholder
235 ? "Yes (Value would not fit to placeholder)"
236
237 : srcIsValue && arrayBoxing && isValueTypeCustomized
238 ? "Yes (Custom unboxing from array type)"
239
240 : srcIsValue && arrayBoxing && isPointerTypeCustomized
241 ? "Yes (Unboxing from array type, customized with pointer type)"
242
243 : srcIsPointer && arrayBoxing && isPointerTypeCustomized
244 ? "Yes (Custom unboxing from array type)"
245
246 : srcIsPointer && arrayBoxing && isValueTypeCustomized
247 ? "Yes (Unboxing from array type, customized with value type)"
248
249 : "INTERNAL ERROR IN DBG METHDO: CASE NOT MATCHED (E1)"
250 )
251 : (
252 srcIsValue && isValueTypeCustomized
253 ? "Forbidden (By customization)"
254
255 : srcIsValue && pointerBoxing && isPointerTypeCustomized
256 ? "Not as value (Pointer type is customized)"
257
258 : srcIsValue && pointerBoxing && !isPointerTypeCustomized && (!copyConstructible || !triviallyDestructible)
259 ? "Not as value (Not copy-constructible or trivially destructible)"
260
261 : srcIsValue && pointerBoxing && !isPointerTypeCustomized && !fitsToPlaceholder
262 ? "Not as value (Does not fit to placeholder)"
263
264 : srcIsPointer && isPointerTypeCustomized
265 ? "Forbidden (By customization)"
266
267 : srcIsPointer && valueBoxing && isValueTypeCustomized
268 ? "Not as pointer (Value type is customized)"
269
270 : srcIsPointer && valueBoxing && !isValueTypeCustomized
271 ? "Not as pointer (Value fits in placeholder and is copy constructible and trivially destructible)"
272
273 : "INTERNAL ERROR IN DBG METHOd: CASE NOT MATCHED (E2)"
274 )
275 ) << NewLine();
276 } // not enum
277
278 target << indent << "VTable Type: " << ( vtable->DbgProduction == detail::VTable::DbgFactoryType::Unregistered
279 ? "INTERNAL ERROR IN DBG METHOD: STATIC VTABLE NOT REGISTERED"
281 ? "Dynamic Singleton"
282 : "Static Singleton (Specialized T_VTableFactory)"
283 )
284 << NewLine();
285
286 target << indent << "Usage Counter: " << vtable->DbgCntUsage << NewLine();
287
288 ALIB_ASSERT_ERROR( target.IndexOf( A_CHAR("INTERNAL ERROR") ) < 0,
289 "BOXING", "Error occurred describing type" )
290
291 auto functions= GetSpecificFunctionTypes(vtable);
292 MonoAllocator allocator(8192);
293 detail::DbgStringTable<uinteger> tmpStrings( allocator );
294 String256 headline; headline << '\n' << indent << "Associated Specialized Functions:";
295 String256 indent2; indent2 << indent << indent;
296 dumpFunctions( functions, target, headline, indent2, tmpStrings );
297}
298
299
300// #############################################################################################
301// Dump Type Lists (conversion for type lists)
302// #############################################################################################
303AString DbgBoxing::DumpFunctions( const std::vector<std::pair<const std::type_info*,uinteger>>& input,
304 const String& headline,
305 const String& indent )
306{
307 AString result;
308 MonoAllocator allocator(8192);
309 detail::DbgStringTable<uinteger> tmpStrings( allocator );
310
311 // repeat twice to get auto-tabs adjusted
313 for( int theSakeOfAutoTabs= 0 ; theSakeOfAutoTabs < 2 ; ++theSakeOfAutoTabs )
314 {
315 result.Reset();
316 dumpFunctions( input, result, headline, indent, tmpStrings );
317 }
318 formatter->Release();
319
320 return result;
321}
322
323void DbgBoxing::dumpFunctions( const std::vector<std::pair<const std::type_info*,uinteger>>& input,
324 AString& output,
325 const String& headline,
326 const String& indent,
328{
329 String512 buffer;
330 tmpStrings.clear();
331 for( auto& type : input )
332 tmpStrings.Add( removeNamespaces(buffer.Reset() << *type.first, 0), type.second );
333
334 std::sort( tmpStrings.begin(), tmpStrings.end(),
335 [] (std::tuple<String, uinteger>& a,
336 std::tuple<String, uinteger>& b )
337 {
338 return std::get<0>(a).template CompareTo<true, lang::Case::Ignore>( std::get<0>(b) ) < 0;
339 }
340 );
341
342 if ( headline.IsNotEmpty() )
343 output << headline << NewLine();
344
346 Boxes& args= formatter->Acquire(ALIB_CALLER_PRUNED);
347 args.Add( indent, "{} {!ATab5}{:>2})\n", nullptr, '(', nullptr );
348 for( auto& nameAndUse : tmpStrings )
349 {
350 args[2]= std::get<0>(nameAndUse);
351 args[4]= std::get<1>(nameAndUse) != (std::numeric_limits<uinteger>::max)()
352 ? Box( std::get<1>(nameAndUse) )
353 : Box( "No default implementation" );
354 formatter->FormatArgs( output, args );
355 }
356 formatter->Release();
357 output << NewLine();
358}
359
360
361// #############################################################################################
362// Dump
363// #############################################################################################
364
365AString DbgBoxing::DumpVTables( bool staticVtables, bool includeFunctions )
366{
367 AString result;
368 MonoAllocator allocator(8192);
369
370 // repeat twice to get auto-tabs adjusted
372
373 for( int theSakeOfAutoTabs= 0 ; theSakeOfAutoTabs < 2 ; ++theSakeOfAutoTabs )
374 {
375 result .Reset();
376 allocator .Reset();
377 detail::DbgStringTable<const detail::VTable*> vtableNames( allocator );
378 dumpVTables( result, vtableNames, staticVtables , includeFunctions );
379 }
380
381 formatter->Release();
382 return result;
383}
384
385
388 bool staticVtables,
389 bool includeFunctions )
390{
392
393 // dump vtables and their interfaces
394 result << ( staticVtables ? A_CHAR("Mapped types with static VTables")
395 : A_CHAR("Mapped types with dynamic VTables") );
396 if( includeFunctions )
397 result << A_CHAR(" and their associated specialized functions");
398
399 (result << ':' << NewLine()) .InsertChars('-', 77) << NewLine();
400
401 // Get vtables and add names to string array
402 vtableNames.clear();
403 String1K temp;
404 detail::DbgLockMaps(true);
405 for( int i= 0 ; i < 2; ++i )
406 for( auto& it : ( i == 0 ? detail::DbgKnownVTables : detail::DbgKnownVTablesArray) )
407 {
408 if( (it.second->DbgProduction == (staticVtables ? detail::VTable::DbgFactoryType::Static
410 || it.second->DbgProduction == detail::VTable::DbgFactoryType::Unregistered )
411 {
412
413 temp.Reset();
414
415 temp << Format::Field( String64("(") << it.second->DbgCntUsage<< ") ", 6, lang::Alignment::Left );
416 typeName( it.second, temp );
417 if( it.second->DbgProduction == detail::VTable::DbgFactoryType::Unregistered )
418 temp << " ATTENTION: Unregistered customized VTable!!! This is an Error";
419
420 vtableNames.Add( temp, it.second );
421 }
422 }
423 detail::DbgLockMaps(false);
424
425 std::sort( vtableNames.begin(), vtableNames.end(),
428 {
429 // skip the prepended usage number
430 Substring lhs= std::get<0>(a); lhs.TrimStart().ConsumeToken(' '); lhs.TrimStart();
431 Substring rhs= std::get<0>(b); rhs.TrimStart().ConsumeToken(' '); rhs.TrimStart();
432 return lhs.CompareTo<true, lang::Case::Ignore>( rhs ) < 0;
433 }
434 );
435
436 MonoAllocator allocator(8192);
437 detail::DbgStringTable<uinteger> tempStrings( allocator );
438 std::vector<std::pair<const std::type_info*,uinteger>> tempFunctions;
439 for( auto& vtable: vtableNames )
440 {
441 result << std::get<0>(vtable) << NewLine();
442 if( includeFunctions )
443 {
444 getFunctionTypes(std::get<1>(vtable)->Functions, tempFunctions );
445 dumpFunctions( tempFunctions, result, NullString(), A_CHAR(" "), tempStrings );
446 }
447 }
448
449 formatter->Release();
450}
451
453{
454 AString result;
455
456 // Get vtables and add names to string array
457 MonoAllocator allocator(8192);
458
459 // repeat twice to get auto-tabs adjusted
461
462 for( int theSakeOfAutoTabs= 0 ; theSakeOfAutoTabs < 2 ; ++theSakeOfAutoTabs )
463 {
464 result .Reset();
465 allocator.Reset();
466 detail::DbgStringTable<const detail::VTable*> vtableNames( allocator );
467 detail::DbgStringTable<uinteger> tempStrings( allocator);
468 dumpVTables( result, vtableNames, true , true ); result.NewLine();
469 dumpVTables( result, vtableNames, false, true ); result.NewLine();
470
471 auto knownFunctions= GetKnownFunctionTypes();
472 (result << "Known Function Declarators And Usage Of Default Implementation:"
473 << NewLine()) .InsertChars('-', 77) << NewLine();
474 dumpFunctions( knownFunctions, result, NullString(), A_CHAR(" "), tempStrings );
475
476 #if ALIB_DEBUG_MONOMEM
477 (result << NewLine() << "Metrics Of Custom Function Implementation HashMap: "
478 << NewLine()) .InsertChars('-', 77) << NewLine();
479 DumpCustomFunctionHashMapMetrics( result, false );
480 result << NewLine();
481 #endif
482 }
483
484 formatter->Release();
485
486 return result;
487}
488
489
490#endif // ALIB_CAMP
491
492}} // namespace [alib::boxing]
493
494#endif // ALIB_DEBUG_BOXING
static SPFormatter GetDefault()
static SPFormatter AcquireDefault(const NCString &dbgFile, int dbgLine, const NCString &dbgFunc)
ALIB_API void Reset(const Snapshot &snapshot=Snapshot())
TAString & DeleteStart(integer regionLength)
Definition astring.hpp:1547
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:889
constexpr bool IsNotEmpty() const
Definition string.hpp:420
constexpr integer Length() const
Definition string.hpp:357
bool StartsWith(const TString &needle) const
Definition string.hpp:813
#define A_CHAR(STR)
#define ALIB_IF_THREADS(...)
Definition alib.hpp:303
#define ALIB_API
Definition alib.hpp:538
#define ALIB_ERROR(...)
Definition alib.hpp:980
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_CALLER_PRUNED
Definition alib.hpp:845
#define ALIB_LOCK_WITH(lock)
void DbgRegisterVTable(detail::VTable *vtable, detail::VTable::DbgFactoryType productionType)
Definition dbgboxing.cpp:96
@ Left
Chooses left alignment.
ALIB_API ThreadLock GlobalAllocatorLock
MonoAllocator GlobalAllocator(8 *1024)
Definition alib.cpp:57
LocalString< 64 > String64
Type alias name for TLocalString<character,64> .
constexpr CString NewLine()
Definition cstring.hpp:528
void DbgCheckSingleThreaded()
Definition alib.cpp:226
constexpr String NullString()
Definition string.hpp:2498
std::shared_ptr< lang::format::Formatter > SPFormatter
threads::ThreadLock ThreadLock
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
static ALIB_API void dumpVTables(AString &target, detail::DbgStringTable< const detail::VTable * > &vtableNames, bool staticVtables, bool includeFunctions)
static ALIB_API AString & removeNamespaces(AString &string, integer startIndex)
static ALIB_API std::vector< std::pair< const std::type_info *, uinteger > > GetKnownFunctionTypes()
Definition vtable.cpp:206
static std::vector< std::pair< const std::type_info *, uinteger > > GetSpecificFunctionTypes(const detail::VTable *vtable)
static ALIB_API void DumpCustomFunctionHashMapMetrics(AString &target, bool detailedBucketList)
Definition vtable.cpp:266
static ALIB_API void typeInfo(AString &target, const detail::VTable *vtable, const String &indent, bool srcIsPointer, bool isValueTypeCustomized, bool isPointerTypeCustomized, bool fitsToPlaceholder, bool copyConstructible, bool triviallyDestructible, bool isUnboxable)
static ALIB_API alib::AString DumpFunctions(const std::vector< std::pair< const std::type_info *, uinteger > > &input, const String &headline=EmptyString(), const String &indent=EmptyString())
static ALIB_API void dumpFunctions(const std::vector< std::pair< const std::type_info *, uinteger > > &input, AString &output, const String &headline, const String &indent, detail::DbgStringTable< uinteger > &tmpStrings)
static ALIB_API void getFunctionTypes(const detail::FunctionTable &input, std::vector< std::pair< const std::type_info *, uinteger > > &output)
Definition vtable.cpp:242
static ALIB_API void typeName(const detail::VTable *vtable, AString &result)
static ALIB_API AString DumpAll()
static ALIB_API std::vector< String > RemovableNamespaces
static ALIB_API AString DumpVTables(bool staticVtables, bool includeFunctions=false)
String & Add(const String &src, TArgs &&... args)
Definition dbgboxing.hpp:83
std::tuple< String, TAssociatedTypes... > ElementType
Definition dbgboxing.hpp:55
DbgFactoryType DbgProduction
Definition vtable.inl:233
const std::type_info & Type
Definition vtable.inl:194
@ Static
A static VTable is in place.
@ Dynamic
The VTable is created dynamically from templated type VTableTT.
const MappingType Mapping
Definition vtable.inl:205
@ Enum
Enum type boxing.
Definition vtable.inl:189
@ Pointer
Pointer boxing.
Definition vtable.inl:188
const std::type_info & ElementType
Definition vtable.inl:198