Refactored all uses of form (1) (See the long description in GlobalsHandling.h) of...
[vuplus_xbmc] / xbmc / SectionLoader.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "system.h"
23 #include "SectionLoader.h"
24 #include "cores/DllLoader/DllLoaderContainer.h"
25 #include "threads/SingleLock.h"
26 #include "utils/log.h"
27 #include "utils/TimeUtils.h"
28
29 using namespace std;
30
31 #define g_sectionLoader XBMC_GLOBAL_USE(CSectionLoader)
32
33 //  delay for unloading dll's
34 #define UNLOAD_DELAY 30*1000 // 30 sec.
35
36 //Define this to get loggin on all calls to load/unload sections/dlls
37 //#define LOGALL
38
39 CSectionLoader::CSectionLoader(void)
40 {}
41
42 CSectionLoader::~CSectionLoader(void)
43 {}
44
45 bool CSectionLoader::IsLoaded(const CStdString& strSection)
46 {
47   CSingleLock lock(g_sectionLoader.m_critSection);
48
49   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedSections.size(); ++i)
50   {
51     CSection& section = g_sectionLoader.m_vecLoadedSections[i];
52     if (section.m_strSectionName == strSection && section.m_lReferenceCount > 0) return true;
53   }
54   return false;
55 }
56
57 bool CSectionLoader::Load(const CStdString& strSection)
58 {
59   CSingleLock lock(g_sectionLoader.m_critSection);
60
61   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedSections.size(); ++i)
62   {
63     CSection& section = g_sectionLoader.m_vecLoadedSections[i];
64     if (section.m_strSectionName == strSection)
65     {
66
67 #ifdef LOGALL
68       CLog::Log(LOGDEBUG,"SECTION:LoadSection(%s) count:%i\n", strSection.c_str(), section.m_lReferenceCount);
69 #endif
70
71       section.m_lReferenceCount++;
72       return true;
73     }
74   }
75
76 #ifdef HAS_SECTIONS
77   if ( NULL == XLoadSection(strSection.c_str() ) )
78   {
79     CLog::Log(LOGDEBUG,"SECTION:LoadSection(%s) load failed!!\n", strSection.c_str());
80     return false;
81   }
82   HANDLE hHandle = XGetSectionHandle(strSection.c_str());
83
84   CLog::Log(LOGDEBUG,"SECTION:Section %s loaded count:1 size:%i\n", strSection.c_str(), XGetSectionSize(hHandle) );
85 #endif
86
87   CSection newSection;
88   newSection.m_strSectionName = strSection;
89   newSection.m_lReferenceCount = 1;
90   g_sectionLoader.m_vecLoadedSections.push_back(newSection);
91   return true;
92 }
93
94 void CSectionLoader::Unload(const CStdString& strSection)
95 {
96   CSingleLock lock(g_sectionLoader.m_critSection);
97   if (!CSectionLoader::IsLoaded(strSection)) return ;
98
99   ivecLoadedSections i;
100   i = g_sectionLoader.m_vecLoadedSections.begin();
101   while (i != g_sectionLoader.m_vecLoadedSections.end())
102   {
103     CSection& section = *i;
104     if (section.m_strSectionName == strSection)
105     {
106 #ifdef LOGALL
107       CLog::Log(LOGDEBUG,"SECTION:FreeSection(%s) count:%i\n", strSection.c_str(), section.m_lReferenceCount);
108 #endif
109       section.m_lReferenceCount--;
110       if ( 0 == section.m_lReferenceCount)
111       {
112         section.m_unloadDelayStartTick = CTimeUtils::GetTimeMS();
113         return ;
114       }
115     }
116     ++i;
117   }
118 }
119
120 LibraryLoader *CSectionLoader::LoadDLL(const CStdString &dllname, bool bDelayUnload /*=true*/, bool bLoadSymbols /*=false*/)
121 {
122   CSingleLock lock(g_sectionLoader.m_critSection);
123
124   if (!dllname) return NULL;
125   // check if it's already loaded, and increase the reference count if so
126   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
127   {
128     CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
129     if (dll.m_strDllName.Equals(dllname))
130     {
131       dll.m_lReferenceCount++;
132       return dll.m_pDll;
133     }
134   }
135
136   // ok, now load the dll
137   CLog::Log(LOGDEBUG, "SECTION:LoadDLL(%s)\n", dllname.c_str());
138   LibraryLoader* pDll = DllLoaderContainer::LoadModule(dllname.c_str(), NULL, bLoadSymbols);
139   if (!pDll)
140     return NULL;
141
142   CDll newDLL;
143   newDLL.m_strDllName = dllname;
144   newDLL.m_lReferenceCount = 1;
145   newDLL.m_bDelayUnload=bDelayUnload;
146   newDLL.m_pDll=pDll;
147   g_sectionLoader.m_vecLoadedDLLs.push_back(newDLL);
148
149   return newDLL.m_pDll;
150 }
151
152 void CSectionLoader::UnloadDLL(const CStdString &dllname)
153 {
154   CSingleLock lock(g_sectionLoader.m_critSection);
155
156   if (!dllname) return;
157   // check if it's already loaded, and decrease the reference count if so
158   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
159   {
160     CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
161     if (dll.m_strDllName.Equals(dllname))
162     {
163       dll.m_lReferenceCount--;
164       if (0 == dll.m_lReferenceCount)
165       {
166         if (dll.m_bDelayUnload)
167           dll.m_unloadDelayStartTick = CTimeUtils::GetTimeMS();
168         else
169         {
170           CLog::Log(LOGDEBUG,"SECTION:UnloadDll(%s)", dllname.c_str());
171           if (dll.m_pDll)
172             DllLoaderContainer::ReleaseModule(dll.m_pDll);
173           g_sectionLoader.m_vecLoadedDLLs.erase(g_sectionLoader.m_vecLoadedDLLs.begin() + i);
174         }
175
176         return;
177       }
178     }
179   }
180 }
181
182 void CSectionLoader::UnloadDelayed()
183 {
184   CSingleLock lock(g_sectionLoader.m_critSection);
185
186   ivecLoadedSections i = g_sectionLoader.m_vecLoadedSections.begin();
187   while( i != g_sectionLoader.m_vecLoadedSections.end() )
188   {
189     CSection& section = *i;
190     if( section.m_lReferenceCount == 0 && CTimeUtils::GetTimeMS() - section.m_unloadDelayStartTick > UNLOAD_DELAY)
191     {
192       CLog::Log(LOGDEBUG,"SECTION:UnloadDelayed(SECTION: %s)", section.m_strSectionName.c_str());
193 #ifdef HAS_SECTIONS
194       XFreeSection(section.m_strSectionName.c_str());
195 #endif
196       i = g_sectionLoader.m_vecLoadedSections.erase(i);
197       continue;
198     }
199     i++;
200   }
201
202   // check if we can unload any unreferenced dlls
203   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
204   {
205     CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
206     if (dll.m_lReferenceCount == 0 && CTimeUtils::GetTimeMS() - dll.m_unloadDelayStartTick > UNLOAD_DELAY)
207     {
208       CLog::Log(LOGDEBUG,"SECTION:UnloadDelayed(DLL: %s)", dll.m_strDllName.c_str());
209
210       if (dll.m_pDll)
211         DllLoaderContainer::ReleaseModule(dll.m_pDll);
212       g_sectionLoader.m_vecLoadedDLLs.erase(g_sectionLoader.m_vecLoadedDLLs.begin() + i);
213       return;
214     }
215   }
216 }
217
218 void CSectionLoader::UnloadAll()
219 {
220   ivecLoadedSections i;
221   i = g_sectionLoader.m_vecLoadedSections.begin();
222   while (i != g_sectionLoader.m_vecLoadedSections.end())
223   {
224     CSection& section = *i;
225     //g_sectionLoader.m_vecLoadedSections.erase(i);
226     CLog::Log(LOGDEBUG,"SECTION:UnloadAll(SECTION: %s)", section.m_strSectionName.c_str());
227 #ifdef HAS_SECTIONS
228     XFreeSection(section.m_strSectionName.c_str());
229 #endif
230     i = g_sectionLoader.m_vecLoadedSections.erase(i);
231   }
232
233   // delete the dll's
234   CSingleLock lock(g_sectionLoader.m_critSection);
235   vector<CDll>::iterator it = g_sectionLoader.m_vecLoadedDLLs.begin();
236   while (it != g_sectionLoader.m_vecLoadedDLLs.end())
237   {
238     CDll& dll = *it;
239     CLog::Log(LOGDEBUG,"SECTION:UnloadAll(DLL: %s)", dll.m_strDllName.c_str());
240     if (dll.m_pDll)
241       DllLoaderContainer::ReleaseModule(dll.m_pDll);
242     it = g_sectionLoader.m_vecLoadedDLLs.erase(it);
243   }
244 }