Merge branch 'opportunisticCacheCheck' of git://github.com/hippojay/xbmc into hippoja...
[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 "threads/SystemClock.h"
23 #include "system.h"
24 #include "SectionLoader.h"
25 #include "cores/DllLoader/DllLoaderContainer.h"
26 #include "threads/SingleLock.h"
27 #include "utils/log.h"
28 #include "utils/TimeUtils.h"
29
30 using namespace std;
31
32 #define g_sectionLoader XBMC_GLOBAL_USE(CSectionLoader)
33
34 //  delay for unloading dll's
35 #define UNLOAD_DELAY 30*1000 // 30 sec.
36
37 //Define this to get loggin on all calls to load/unload sections/dlls
38 //#define LOGALL
39
40 CSectionLoader::CSectionLoader(void)
41 {}
42
43 CSectionLoader::~CSectionLoader(void)
44 {
45   UnloadAll();
46 }
47
48 bool CSectionLoader::IsLoaded(const CStdString& strSection)
49 {
50   CSingleLock lock(g_sectionLoader.m_critSection);
51
52   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedSections.size(); ++i)
53   {
54     CSection& section = g_sectionLoader.m_vecLoadedSections[i];
55     if (section.m_strSectionName == strSection && section.m_lReferenceCount > 0) return true;
56   }
57   return false;
58 }
59
60 bool CSectionLoader::Load(const CStdString& strSection)
61 {
62   CSingleLock lock(g_sectionLoader.m_critSection);
63
64   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedSections.size(); ++i)
65   {
66     CSection& section = g_sectionLoader.m_vecLoadedSections[i];
67     if (section.m_strSectionName == strSection)
68     {
69
70 #ifdef LOGALL
71       CLog::Log(LOGDEBUG,"SECTION:LoadSection(%s) count:%i\n", strSection.c_str(), section.m_lReferenceCount);
72 #endif
73
74       section.m_lReferenceCount++;
75       return true;
76     }
77   }
78
79 #ifdef HAS_SECTIONS
80   if ( NULL == XLoadSection(strSection.c_str() ) )
81   {
82     CLog::Log(LOGDEBUG,"SECTION:LoadSection(%s) load failed!!\n", strSection.c_str());
83     return false;
84   }
85   HANDLE hHandle = XGetSectionHandle(strSection.c_str());
86
87   CLog::Log(LOGDEBUG,"SECTION:Section %s loaded count:1 size:%i\n", strSection.c_str(), XGetSectionSize(hHandle) );
88 #endif
89
90   CSection newSection;
91   newSection.m_strSectionName = strSection;
92   newSection.m_lReferenceCount = 1;
93   g_sectionLoader.m_vecLoadedSections.push_back(newSection);
94   return true;
95 }
96
97 void CSectionLoader::Unload(const CStdString& strSection)
98 {
99   CSingleLock lock(g_sectionLoader.m_critSection);
100   if (!CSectionLoader::IsLoaded(strSection)) return ;
101
102   ivecLoadedSections i;
103   i = g_sectionLoader.m_vecLoadedSections.begin();
104   while (i != g_sectionLoader.m_vecLoadedSections.end())
105   {
106     CSection& section = *i;
107     if (section.m_strSectionName == strSection)
108     {
109 #ifdef LOGALL
110       CLog::Log(LOGDEBUG,"SECTION:FreeSection(%s) count:%i\n", strSection.c_str(), section.m_lReferenceCount);
111 #endif
112       section.m_lReferenceCount--;
113       if ( 0 == section.m_lReferenceCount)
114       {
115         section.m_unloadDelayStartTick = XbmcThreads::SystemClockMillis();
116         return ;
117       }
118     }
119     ++i;
120   }
121 }
122
123 LibraryLoader *CSectionLoader::LoadDLL(const CStdString &dllname, bool bDelayUnload /*=true*/, bool bLoadSymbols /*=false*/)
124 {
125   CSingleLock lock(g_sectionLoader.m_critSection);
126
127   if (!dllname) return NULL;
128   // check if it's already loaded, and increase the reference count if so
129   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
130   {
131     CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
132     if (dll.m_strDllName.Equals(dllname))
133     {
134       dll.m_lReferenceCount++;
135       return dll.m_pDll;
136     }
137   }
138
139   // ok, now load the dll
140   CLog::Log(LOGDEBUG, "SECTION:LoadDLL(%s)\n", dllname.c_str());
141   LibraryLoader* pDll = DllLoaderContainer::LoadModule(dllname.c_str(), NULL, bLoadSymbols);
142   if (!pDll)
143     return NULL;
144
145   CDll newDLL;
146   newDLL.m_strDllName = dllname;
147   newDLL.m_lReferenceCount = 1;
148   newDLL.m_bDelayUnload=bDelayUnload;
149   newDLL.m_pDll=pDll;
150   g_sectionLoader.m_vecLoadedDLLs.push_back(newDLL);
151
152   return newDLL.m_pDll;
153 }
154
155 void CSectionLoader::UnloadDLL(const CStdString &dllname)
156 {
157   CSingleLock lock(g_sectionLoader.m_critSection);
158
159   if (!dllname) return;
160   // check if it's already loaded, and decrease the reference count if so
161   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
162   {
163     CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
164     if (dll.m_strDllName.Equals(dllname))
165     {
166       dll.m_lReferenceCount--;
167       if (0 == dll.m_lReferenceCount)
168       {
169         if (dll.m_bDelayUnload)
170           dll.m_unloadDelayStartTick = XbmcThreads::SystemClockMillis();
171         else
172         {
173           CLog::Log(LOGDEBUG,"SECTION:UnloadDll(%s)", dllname.c_str());
174           if (dll.m_pDll)
175             DllLoaderContainer::ReleaseModule(dll.m_pDll);
176           g_sectionLoader.m_vecLoadedDLLs.erase(g_sectionLoader.m_vecLoadedDLLs.begin() + i);
177         }
178
179         return;
180       }
181     }
182   }
183 }
184
185 void CSectionLoader::UnloadDelayed()
186 {
187   CSingleLock lock(g_sectionLoader.m_critSection);
188
189   ivecLoadedSections i = g_sectionLoader.m_vecLoadedSections.begin();
190   while( i != g_sectionLoader.m_vecLoadedSections.end() )
191   {
192     CSection& section = *i;
193     if( section.m_lReferenceCount == 0 && XbmcThreads::SystemClockMillis() - section.m_unloadDelayStartTick > UNLOAD_DELAY)
194     {
195       CLog::Log(LOGDEBUG,"SECTION:UnloadDelayed(SECTION: %s)", section.m_strSectionName.c_str());
196 #ifdef HAS_SECTIONS
197       XFreeSection(section.m_strSectionName.c_str());
198 #endif
199       i = g_sectionLoader.m_vecLoadedSections.erase(i);
200       continue;
201     }
202     i++;
203   }
204
205   // check if we can unload any unreferenced dlls
206   for (int i = 0; i < (int)g_sectionLoader.m_vecLoadedDLLs.size(); ++i)
207   {
208     CDll& dll = g_sectionLoader.m_vecLoadedDLLs[i];
209     if (dll.m_lReferenceCount == 0 && XbmcThreads::SystemClockMillis() - dll.m_unloadDelayStartTick > UNLOAD_DELAY)
210     {
211       CLog::Log(LOGDEBUG,"SECTION:UnloadDelayed(DLL: %s)", dll.m_strDllName.c_str());
212
213       if (dll.m_pDll)
214         DllLoaderContainer::ReleaseModule(dll.m_pDll);
215       g_sectionLoader.m_vecLoadedDLLs.erase(g_sectionLoader.m_vecLoadedDLLs.begin() + i);
216       return;
217     }
218   }
219 }
220
221 void CSectionLoader::UnloadAll()
222 {
223   ivecLoadedSections i;
224   i = g_sectionLoader.m_vecLoadedSections.begin();
225   while (i != g_sectionLoader.m_vecLoadedSections.end())
226   {
227     CSection& section = *i;
228     //g_sectionLoader.m_vecLoadedSections.erase(i);
229     CLog::Log(LOGDEBUG,"SECTION:UnloadAll(SECTION: %s)", section.m_strSectionName.c_str());
230 #ifdef HAS_SECTIONS
231     XFreeSection(section.m_strSectionName.c_str());
232 #endif
233     i = g_sectionLoader.m_vecLoadedSections.erase(i);
234   }
235
236   // delete the dll's
237   CSingleLock lock(g_sectionLoader.m_critSection);
238   vector<CDll>::iterator it = g_sectionLoader.m_vecLoadedDLLs.begin();
239   while (it != g_sectionLoader.m_vecLoadedDLLs.end())
240   {
241     CDll& dll = *it;
242     CLog::Log(LOGDEBUG,"SECTION:UnloadAll(DLL: %s)", dll.m_strDllName.c_str());
243     if (dll.m_pDll)
244       DllLoaderContainer::ReleaseModule(dll.m_pDll);
245     it = g_sectionLoader.m_vecLoadedDLLs.erase(it);
246   }
247 }