1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "AddonClass.h"
10 #ifdef XBMC_ADDON_DEBUG_MEMORY
11 #include "utils/log.h"
12 #endif
13 #include "LanguageHook.h"
14 #include "AddonUtils.h"
15 
16 using namespace XBMCAddonUtils;
17 
18 namespace XBMCAddon
19 {
20   // need a place to put the vtab
~AddonClass()21   AddonClass::~AddonClass()
22   {
23     m_isDeallocating= true;
24 
25     if (languageHook != NULL)
26       languageHook->Release();
27 
28 #ifdef XBMC_ADDON_DEBUG_MEMORY
29     isDeleted = false;
30 #endif
31   }
32 
AddonClass()33   AddonClass::AddonClass() : refs(0L),
34                              languageHook(NULL)
35   {
36 #ifdef XBMC_ADDON_DEBUG_MEMORY
37     isDeleted = false;
38 #endif
39 
40     // check to see if we have a language hook that was prepared for this instantiation
41     languageHook = LanguageHook::GetLanguageHook();
42     if (languageHook != NULL)
43     {
44       languageHook->Acquire();
45 
46       // here we assume the language hook was set for the single instantiation of
47       //  this AddonClass (actually - its subclass - but whatever). So we
48       //  will now reset the Tls. This avoids issues if the constructor of the
49       //  subclass throws an exception.
50       LanguageHook::ClearLanguageHook();
51     }
52   }
53 
54 #ifdef XBMC_ADDON_DEBUG_MEMORY
Release() const55   void AddonClass::Release() const
56   {
57     if (isDeleted)
58       CLog::Log(LOGERROR,"NEWADDON REFCNT Releasing dead class %s 0x%lx",
59                 GetClassname(), (long)(((void*)this)));
60 
61     long ct = --refs;
62 #ifdef LOG_LIFECYCLE_EVENTS
63     CLog::Log(LOGDEBUG,"NEWADDON REFCNT decrementing to %ld on %s 0x%lx", refs.load(), GetClassname(), (long)(((void*)this)));
64 #endif
65     if(ct == 0)
66     {
67         const_cast<AddonClass*>(this)->isDeleted = true;
68         // we're faking a delete but not doing it so call the destructor explicitly
69         this->~AddonClass();
70     }
71   }
72 
Acquire() const73   void AddonClass::Acquire() const
74   {
75     if (isDeleted)
76       CLog::Log(LOGERROR,"NEWADDON REFCNT Acquiring dead class %s 0x%lx",
77                 GetClassname(), (long)(((void*)this)));
78 
79 #ifdef LOG_LIFECYCLE_EVENTS
80     CLog::Log(LOGDEBUG,"NEWADDON REFCNT incrementing to %ld on %s 0x%lx",
81               ++refs, GetClassname(), (long)(((void*)this)));
82 #else
83     ++refs;
84 #endif
85   }
86 #endif
87 }
88 
89 
90