2 * Copyright (C) 2011-2013 Team XBMC
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)
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.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "PipesManager.h"
22 #include "threads/SingleLock.h"
25 #define min(a,b) ((a) < (b) ? (a) : (b))
28 using namespace XFILE;
31 Pipe::Pipe(const CStdString &name, int nMaxSize)
33 m_buffer.Create(nMaxSize);
40 m_nOpenThreashold = PIPE_DEFAULT_MAX_SIZE / 2;
41 m_bReadyForRead = true; // open threashold disabled atm
48 void Pipe::SetOpenThreashold(int threashold)
50 m_nOpenThreashold = threashold;
53 const CStdString &Pipe::GetName()
60 CSingleLock lock(m_lock);
66 CSingleLock lock(m_lock);
72 CSingleLock lock(m_lock);
88 return (m_buffer.getMaxReadSize() == 0);
93 CSingleLock lock(m_lock);
95 if (!m_bOpen || !m_bReadyForRead || m_bEof)
103 int Pipe::Read(char *buf, int nMaxSize, int nWaitMillis)
105 CSingleLock lock(m_lock);
112 while (!m_bReadyForRead && !m_bEof)
113 m_readEvent.WaitMSec(100);
118 int nToRead = min((int)m_buffer.getMaxReadSize(), nMaxSize);
119 m_buffer.ReadData(buf, nToRead);
128 // we're leaving the guard - add ref to make sure we are not getting erased.
129 // at the moment we leave m_listeners unprotected which might be a problem in future
130 // but as long as we only have 1 listener attaching at startup and detaching on close we're fine
134 bool bHasData = false;
135 int nMillisLeft = nWaitMillis;
137 nMillisLeft = 5*60*1000; // arbitrary. 5 min.
141 for (size_t l=0; l<m_listeners.size(); l++)
142 m_listeners[l]->OnPipeUnderFlow();
144 bHasData = m_readEvent.WaitMSec(min(200,nMillisLeft));
146 } while (!bHasData && nMillisLeft > 0 && !m_bEof);
156 int nToRead = min((int)m_buffer.getMaxReadSize(), nMaxSize);
157 m_buffer.ReadData(buf, nToRead);
167 bool Pipe::Write(const char *buf, int nSize, int nWaitMillis)
169 CSingleLock lock(m_lock);
173 int writeSize = m_buffer.getMaxWriteSize();
174 if (writeSize > nSize)
176 m_buffer.WriteData((char*)buf, nSize);
181 while ( (int)m_buffer.getMaxWriteSize() < nSize && m_bOpen )
184 for (size_t l=0; l<m_listeners.size(); l++)
185 m_listeners[l]->OnPipeOverFlow();
187 bool bClear = nWaitMillis < 0 ? m_writeEvent.Wait() : m_writeEvent.WaitMSec(nWaitMillis);
189 if (bClear && (int)m_buffer.getMaxWriteSize() >= nSize)
191 m_buffer.WriteData((char*)buf, nSize);
196 // FIXME: is this right? Shouldn't we see if the time limit has been reached?
204 return bOk && m_bOpen;
207 void Pipe::CheckStatus()
216 if (m_buffer.getMaxWriteSize() == 0)
217 m_writeEvent.Reset();
221 if (m_buffer.getMaxReadSize() == 0)
225 if (!m_bReadyForRead && (int)m_buffer.getMaxReadSize() >= m_nOpenThreashold)
226 m_bReadyForRead = true;
233 CSingleLock lock(m_lock);
239 void Pipe::AddListener(IPipeListener *l)
241 CSingleLock lock(m_lock);
242 for (size_t i=0; i<m_listeners.size(); i++)
244 if (m_listeners[i] == l)
247 m_listeners.push_back(l);
250 void Pipe::RemoveListener(IPipeListener *l)
252 CSingleLock lock(m_lock);
253 std::vector<XFILE::IPipeListener *>::iterator i = m_listeners.begin();
254 while(i != m_listeners.end())
257 i = m_listeners.erase(i);
263 int Pipe::GetAvailableRead()
265 CSingleLock lock(m_lock);
266 return m_buffer.getMaxReadSize();
269 PipesManager::PipesManager() : m_nGenIdHelper(1)
273 PipesManager::~PipesManager()
277 PipesManager &PipesManager::GetInstance()
279 static PipesManager instance;
283 CStdString PipesManager::GetUniquePipeName()
285 CSingleLock lock(m_lock);
287 id.Format("pipe://%d/",m_nGenIdHelper++);
291 XFILE::Pipe *PipesManager::CreatePipe(const CStdString &name, int nMaxPipeSize)
293 CStdString pName = name;
295 pName = GetUniquePipeName();
297 CSingleLock lock(m_lock);
298 if (m_pipes.find(pName) != m_pipes.end())
301 XFILE::Pipe *p = new XFILE::Pipe(pName, nMaxPipeSize);
306 XFILE::Pipe *PipesManager::OpenPipe(const CStdString &name)
308 CSingleLock lock(m_lock);
309 if (m_pipes.find(name) == m_pipes.end())
311 m_pipes[name]->AddRef();
312 return m_pipes[name];
315 void PipesManager::ClosePipe(XFILE::Pipe *pipe)
317 CSingleLock lock(m_lock);
323 if (pipe->RefCount() == 0)
325 m_pipes.erase(pipe->GetName());
330 bool PipesManager::Exists(const CStdString &name)
332 CSingleLock lock(m_lock);
333 return (m_pipes.find(name) != m_pipes.end());