📄 directory.cpp
字号:
/******************************************************************************** directory.cpp: programs definition and registration*-------------------------------------------------------------------------------* (c)1999-2001 VideoLAN* $Id: directory.cpp,v 1.2 2002/09/26 16:05:34 jpsaman Exp $** Authors: Benoit Steiner <benny@via.ecp.fr>** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**-------------------------------------------------------------------------------* TO DO: finir le locking et le tester*******************************************************************************///------------------------------------------------------------------------------// Preamble//------------------------------------------------------------------------------#include "../core/defs.h"#include "config.h"#include "../core/core.h"#include "program.h"#include "broadcast.h"#include "request.h"#include "input.h"#include "repository.h"#include "directory.h"#include "repository.cpp"/******************************************************************************** C_PgrmProvider class****************************************************************************************************************************************************************/C_PgrmInfo::C_PgrmInfo(const C_Program& cProgram) : m_cProgram(cProgram), m_cProviders(20, false){}const C_Program* C_PgrmInfo::GetProgram() const{ return &m_cProgram;}const C_Vector<C_Input>& C_PgrmInfo::GetProviders() const{ return m_cProviders;}bool C_PgrmInfo::IsProvider(C_Input* pInput) const{ ASSERT(pInput); return m_cProviders.Find(*pInput) >= 0;}void C_PgrmInfo::AddProvider(C_Input* pInput){ ASSERT(pInput); ASSERT(!m_cProviders.Find(*pInput) >= 0); m_cProviders.Add(pInput);}bool C_PgrmInfo::DeleteProvider(C_Input* pInput){ ASSERT(pInput); ASSERT(!m_cProviders.Find(*pInput) < 0);//m_cProviders.Delete(pInput); return false;}/******************************************************************************** C_PgrmDirectoryBrowser class****************************************************************************************************************************************************************/C_PgrmDirectoryBrowser::C_PgrmDirectoryBrowser(const C_PgrmDirectory& cDir) : m_cBrowser(cDir.m_cPgrmList.CreateBrowser()){}bool C_PgrmDirectoryBrowser::HasNext(){ return m_cBrowser.HasNextItem();}C_PgrmInfo* C_PgrmDirectoryBrowser::GetNext(){ return m_cBrowser.GetNextItem();}/******************************************************************************** C_PgrmDirectory class****************************************************************************************************************************************************************/C_PgrmDirectory::C_PgrmDirectory(){}C_PgrmDirectory::~C_PgrmDirectory(){}void C_PgrmDirectory::Lock(){ m_cPgrmList.Lock();}void C_PgrmDirectory::UnLock(){ m_cPgrmList.UnLock();}int C_PgrmDirectory::Add(const C_Program& cProgram, C_Input* pInput){ ASSERT(pInput); C_String strPgrmName = cProgram.GetName(); C_PgrmInfo* pInfo = m_cPgrmList.Find(strPgrmName); if(pInfo) { pInfo->AddProvider(pInput); } else { pInfo = new C_PgrmInfo(cProgram); pInfo->AddProvider(pInput); m_cPgrmList.Add(strPgrmName, pInfo); } return NO_ERR;}int C_PgrmDirectory::Remove(const C_Program& cProgram, C_Input* pInput){ ASSERT(pInput); int iRc = GEN_ERR; C_String strPgrmName = cProgram.GetName(); C_PgrmInfo* pInfo = m_cPgrmList.Find(strPgrmName); if(pInfo) { //pInfo->DeleteProvider(pInput); iRc = m_cPgrmList.Remove(strPgrmName); } return iRc;}void C_PgrmDirectory::Empty(C_Input* pInput){}const C_Program* C_PgrmDirectory::GetPgrm(const C_String& strName){ C_PgrmInfo* pInfo = m_cPgrmList.Get(strName); if(pInfo) return pInfo->GetProgram(); else return NULL;}void C_PgrmDirectory::ReleasePgrm(const C_String& strName){ m_cPgrmList.Release(strName);}C_PgrmDirectoryBrowser C_PgrmDirectory::CreateBrowser(){ return C_PgrmDirectoryBrowser(*this);}/******************************************************************************** old C_PgrmDirectory class********************************************************************************* The locking rules are the following:* - A program is locked when accessed (GetPgrm method) or when its directory* is locked* - The directory wait for all the locks on its programs to be released before* locking itself. This involves that no lock on a program should be kept for a* long period.** Lock checks are only made in DEBUG mode for efficiency reasons*******************************************************************************///------------------------------------------------------------------------------// Usefull macro//------------------------------------------------------------------------------/*#ifdef DEBUG#define DEBUG_LOCK(pPgrm) \ (pPgrm)->Lock();#define DEBUG_UNLOCK(pPgrm) \ (pPgrm)->UnLock();#else#define DEBUG_LOCK(pPgrm)#define DEBUG_UNLOCK(pPgrm)#endif//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_PgrmDirectory::C_PgrmDirectory(){ m_iPendingModifs = 0;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_PgrmDirectory::~C_PgrmDirectory(){ // All the programs must be locked in debug mode to be deleted#ifdef DEBUG C_ListIterator<C_Program> cDbgItLock = m_cPgrms.CreateIterator(); while(cDbgItLock.HasNext()) { C_Program* pPgrm = cDbgItLock.GetNext(); pPgrm->Lock(); }#endif}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_PgrmDirectory::Lock(){ // Wait for all the locks on programs to be released and then keep the lock // on m_cModifAllowed m_cModifAllowed.Protect(); while(m_iPendingModifs > 0) { m_cModifAllowed.Wait(); } //printf("Locking dir\n");#ifdef DEBUG // Directory locking m_bIsLocked = true; m_pLockOwner = C_Thread::Self(); // Lock all the pgrms C_ListIterator<C_Program> cDbgItLock = m_cPgrms.CreateIterator(); while(cDbgItLock.HasNext()) { C_Program* pPgrm = cDbgItLock.GetNext(); pPgrm->Lock(); }#endif}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_PgrmDirectory::UnLock(){ ASSERT(m_bIsLocked); ASSERT(m_iPendingModifs == 0); #ifdef DEBUG // Unlock all the pgrms C_ListIterator<C_Program> cDbgItLock = m_cPgrms.CreateIterator(); while(cDbgItLock.HasNext()) { C_Program* pPgrm = cDbgItLock.GetNext(); pPgrm->UnLock(); } // Directory unlocking m_bIsLocked = false;#endif //printf("Unlocking dir\n"); // Release the lock on m_cModifAllowed m_cModifAllowed.Release();}//------------------------------------------------------------------------------// Return GEN_ERR if the program already exist//------------------------------------------------------------------------------int C_PgrmDirectory::AddPgrm(C_Program* pProgram){ ASSERT(pProgram); // The directory should have been locked before ASSERT(m_bIsLocked); ASSERT(m_pLockOwner == C_Thread::Self()); // The program should also have been locked ASSERT(pProgram->m_bIsLocked); ASSERT(pProgram->m_pLockOwner == C_Thread::Self()); int iRc = m_cPgrms.Find(*pProgram); if(iRc >= 0) iRc = GEN_ERR; else { m_cPgrms.PushEnd(pProgram);#ifndef DEBUG // If we are not in debug mode, the global lock on the directory is used // to lock all the programs, we therefore must release the program specific // lock pProgram->UnLock();#endif iRc = NO_ERR; } return iRc;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------int C_PgrmDirectory::RemovePgrm(u16 iPgrmNumber){ // The directory should have been locked before ASSERT(m_bIsLocked); ASSERT(m_pLockOwner == C_Thread::Self()); int iRc = NO_ERR; // Dummy program used by the C_List to look for the program we are // interested in C_Program cPgrm(iPgrmNumber, "No Name"); int iProgramIndex = m_cPgrms.Find(cPgrm); if(iProgramIndex < 0) iRc = GEN_ERR; else { // Program should have been locked in debug mode ASSERT(m_cPgrms[iProgramIndex].m_bIsLocked); m_cPgrms.Delete(iProgramIndex); } return iRc;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_PgrmDirectory::EmptyPgrmList(){ ASSERT(m_bIsLocked); ASSERT(m_pLockOwner == C_Thread::Self()); for(unsigned int iIndex = 0; iIndex < m_cPgrms.Size(); iIndex++) { m_cPgrms.Delete(iIndex); }}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Program* C_PgrmDirectory::GetPgrm(u16 iPgrmNumber){ C_Program* pPgrm = NULL; bool bFound = false; // If a lock on the directory is owned, the [] operator should be used instead ASSERT(!(m_bIsLocked && m_pLockOwner == C_Thread::Self())); // First lock the directory to avoid any modification m_cModifAllowed.Protect(); //printf("Directory protected\n"); C_ListIterator<C_Program> cIterator = m_cPgrms.CreateIterator(); while(cIterator.HasNext()) { pPgrm = cIterator.GetNext(); ASSERT(pPgrm); DEBUG_LOCK(pPgrm); u16 iCurrentPgrm = pPgrm->GetPgrmNumber(); DEBUG_UNLOCK(pPgrm); if(iCurrentPgrm == iPgrmNumber) { // Increase the modification counter. This must be done before locking // the program. Just think about it to find why :) m_iPendingModifs++; // Also lock the pgrm itself. pPgrm->Lock(); // Here we are bFound = true; break; } } // We can now signal the modification m_cModifAllowed.Broadcast(); //printf("Directory unprotected\n"); if(!bFound) pPgrm = NULL; return pPgrm;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Program* C_PgrmDirectory::GetPgrm(const C_String& strName){ C_Program* pPgrm = NULL; bool bFound = false; // If a lock on the directory is owned, the [] operator should be used instead ASSERT(!(m_bIsLocked && m_pLockOwner == C_Thread::Self())); // First lock the directory to avoid any modification m_cModifAllowed.Protect(); //printf("Directory protected\n"); C_ListIterator<C_Program> cIterator = m_cPgrms.CreateIterator(); while(cIterator.HasNext()) { pPgrm = cIterator.GetNext(); ASSERT(pPgrm); DEBUG_LOCK(pPgrm); C_String strCurrentPgrm = pPgrm->GetName(); DEBUG_UNLOCK(pPgrm); if(strCurrentPgrm == strName) { // Increase the modification counter. This must be done before locking // the program. Just think about it to find why :) m_iPendingModifs++; // Also lock the pgrm itself pPgrm->Lock(); // Here we are bFound = true; break; } } // We can now signal the modification m_cModifAllowed.Broadcast(); //printf("Directory unprotected\n"); if(!bFound) pPgrm = NULL; return pPgrm;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_PgrmDirectory::ReleasePgrm(C_Program* pPgrm){ ASSERT(pPgrm); ASSERT(m_iPendingModifs > 0); // First lock the directory to avoid any modification m_cModifAllowed.Protect(); pPgrm->UnLock(); // Decrease the modification counter. This must be done after unlocking // the program. Just think about it to find why :) m_iPendingModifs--; m_cModifAllowed.Broadcast();}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Program& C_PgrmDirectory::operator [] (const unsigned int iIndex){ ASSERT(iIndex < m_cPgrms.Size()); ASSERT(m_bIsLocked); ASSERT(m_pLockOwner == C_Thread::Self()); return m_cPgrms[iIndex];}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------unsigned int C_PgrmDirectory::GetSize() const{ ASSERT(m_bIsLocked); ASSERT(m_pLockOwner == C_Thread::Self()); return m_cPgrms.Size();}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -