diff --git a/Source/ASDisplayNode.mm b/Source/ASDisplayNode.mm index 83e333a01..8eeba8cd9 100644 --- a/Source/ASDisplayNode.mm +++ b/Source/ASDisplayNode.mm @@ -310,6 +310,7 @@ - (void)_staticInitialize - (void)_initializeInstance { [self _staticInitialize]; + __instanceLock__.SetDebugNameWithObject(self); #if ASEVENTLOG_ENABLE _eventLog = [[ASEventLog alloc] initWithObject:self]; diff --git a/Source/Base/ASLog.h b/Source/Base/ASLog.h index ccab4b8e5..80f7e2a1d 100644 --- a/Source/Base/ASLog.h +++ b/Source/Base/ASLog.h @@ -66,6 +66,9 @@ AS_EXTERN os_log_t ASImageLoadingLog(void); #define ASMainThreadDeallocationLogEnabled 0 AS_EXTERN os_log_t ASMainThreadDeallocationLog(void); +#define ASLockingLogEnabled 0 +AS_EXTERN os_log_t ASLockingLog(void); + /** * The activity tracing system changed a lot between iOS 9 and 10. * In iOS 10, the system was merged with logging and became much more powerful diff --git a/Source/Base/ASLog.mm b/Source/Base/ASLog.mm index 270246454..02daf2ea8 100644 --- a/Source/Base/ASLog.mm +++ b/Source/Base/ASLog.mm @@ -46,3 +46,7 @@ os_log_t ASImageLoadingLog() { os_log_t ASMainThreadDeallocationLog() { return (ASMainThreadDeallocationLogEnabled && ASLoggingIsEnabled()) ? ASCreateOnce(as_log_create("org.TextureGroup.Texture", "MainDealloc")) : OS_LOG_DISABLED; } + +os_log_t ASLockingLog() { + return (ASLockingLogEnabled && ASLoggingIsEnabled()) ? ASCreateOnce(as_log_create("org.TextureGroup.Texture", "Locking")) : OS_LOG_DISABLED; +} diff --git a/Source/Details/ASThread.h b/Source/Details/ASThread.h index 9faa35743..78421fe6e 100644 --- a/Source/Details/ASThread.h +++ b/Source/Details/ASThread.h @@ -16,6 +16,8 @@ #import #import #import +#import +#import #import ASDISPLAYNODE_INLINE AS_WARN_UNUSED_RESULT BOOL ASDisplayNodeThreadIsMain() @@ -117,6 +119,12 @@ namespace AS { /// Constructs a plain mutex (the default). Mutex () : Mutex (false) {} + void SetDebugNameWithObject(id object) { +#if ASEnableVerboseLogging && ASDISPLAYNODE_ASSERTIONS_ENABLED + _debug_name = std::string(ASObjectDescriptionMakeTiny(object).UTF8String); +#endif + } + ~Mutex () { // Manually destroy since unions can't do it. switch (_type) { @@ -243,6 +251,11 @@ namespace AS { void WillUnlock() { #if ASDISPLAYNODE_ASSERTIONS_ENABLED +#if ASEnableVerboseLogging + if (!_debug_name.empty()) { + as_log_verbose(ASLockingLog(), "unlock %s, count is %d", _debug_name.c_str(), (int)(_count - 1)); + } +#endif if (--_count == 0) { _owner = std::thread::id(); } @@ -251,6 +264,11 @@ namespace AS { void DidLock() { #if ASDISPLAYNODE_ASSERTIONS_ENABLED +#if ASEnableVerboseLogging + if (!_debug_name.empty()) { + as_log_verbose(ASLockingLog(), "lock %s, count is %d", _debug_name.c_str(), (int)(_count + 1)); + } +#endif if (++_count == 1) { // New owner. _owner = std::this_thread::get_id(); @@ -265,6 +283,10 @@ namespace AS { std::mutex _plain; std::recursive_mutex _recursive; }; +#if ASEnableVerboseLogging + std::string _debug_name; +#endif + #if ASDISPLAYNODE_ASSERTIONS_ENABLED std::thread::id _owner = std::thread::id(); int _count = 0;