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"
23 #include "utils/StringUtils.h"
26 #define min(a,b) ((a) < (b) ? (a) : (b))
29 using namespace XFILE;
32 Pipe::Pipe(const CStdString &name, int nMaxSize)
34 m_buffer.Create(nMaxSize);
41 m_nOpenThreashold = PIPE_DEFAULT_MAX_SIZE / 2;
42 m_bReadyForRead = true; // open threashold disabled atm
49 void Pipe::SetOpenThreashold(int threashold)
51 m_nOpenThreashold = threashold;
54 const CStdString &Pipe::GetName()
61 CSingleLock lock(m_lock);
67 CSingleLock lock(m_lock);
73 CSingleLock lock(m_lock);
89 return (m_buffer.getMaxReadSize() == 0);
94 CSingleLock lock(m_lock);
96 if (!m_bOpen || !m_bReadyForRead || m_bEof)
104 int Pipe::Read(char *buf, int nMaxSize, int nWaitMillis)
106 CSingleLock lock(m_lock);
113 while (!m_bReadyForRead && !m_bEof)
114 m_readEvent.WaitMSec(100);
119 int nToRead = min((int)m_buffer.getMaxReadSize(), nMaxSize);
120 m_buffer.ReadData(buf, nToRead);
129 // we're leaving the guard - add ref to make sure we are not getting erased.
130 // at the moment we leave m_listeners unprotected which might be a problem in future
131 // but as long as we only have 1 listener attaching at startup and detaching on close we're fine
135 bool bHasData = false;
136 int nMillisLeft = nWaitMillis;
138 nMillisLeft = 5*60*1000; // arbitrary. 5 min.
142 for (size_t l=0; l<m_listeners.size(); l++)
143 m_listeners[l]->OnPipeUnderFlow();
145 bHasData = m_readEvent.WaitMSec(min(200,nMillisLeft));
147 } while (!bHasData && nMillisLeft > 0 && !m_bEof);
157 int nToRead = min((int)m_buffer.getMaxReadSize(), nMaxSize);
158 m_buffer.ReadData(buf, nToRead);
168 bool Pipe::Write(const char *buf, int nSize, int nWaitMillis)
170 CSingleLock lock(m_lock);
174 int writeSize = m_buffer.getMaxWriteSize();
175 if (writeSize > nSize)
177 m_buffer.WriteData((char*)buf, nSize);
182 while ( (int)m_buffer.getMaxWriteSize() < nSize && m_bOpen )
185 for (size_t l=0; l<m_listeners.size(); l++)
186 m_listeners[l]->OnPipeOverFlow();
188 bool bClear = nWaitMillis < 0 ? m_writeEvent.Wait() : m_writeEvent.WaitMSec(nWaitMillis);
190 if (bClear && (int)m_buffer.getMaxWriteSize() >= nSize)
192 m_buffer.WriteData((char*)buf, nSize);
197 // FIXME: is this right? Shouldn't we see if the time limit has been reached?
205 return bOk && m_bOpen;
208 void Pipe::CheckStatus()
217 if (m_buffer.getMaxWriteSize() == 0)
218 m_writeEvent.Reset();
222 if (m_buffer.getMaxReadSize() == 0)
226 if (!m_bReadyForRead && (int)m_buffer.getMaxReadSize() >= m_nOpenThreashold)
227 m_bReadyForRead = true;
234 CSingleLock lock(m_lock);
240 void Pipe::AddListener(IPipeListener *l)
242 CSingleLock lock(m_lock);
243 for (size_t i=0; i<m_listeners.size(); i++)
245 if (m_listeners[i] == l)
248 m_listeners.push_back(l);
251 void Pipe::RemoveListener(IPipeListener *l)
253 CSingleLock lock(m_lock);
254 std::vector<XFILE::IPipeListener *>::iterator i = m_listeners.begin();
255 while(i != m_listeners.end())
258 i = m_listeners.erase(i);
264 int Pipe::GetAvailableRead()
266 CSingleLock lock(m_lock);
267 return m_buffer.getMaxReadSize();
270 PipesManager::PipesManager() : m_nGenIdHelper(1)
274 PipesManager::~PipesManager()
278 PipesManager &PipesManager::GetInstance()
280 static PipesManager instance;
284 CStdString PipesManager::GetUniquePipeName()
286 CSingleLock lock(m_lock);
287 return StringUtils::Format("pipe://%d/", m_nGenIdHelper++);
290 XFILE::Pipe *PipesManager::CreatePipe(const CStdString &name, int nMaxPipeSize)
292 CStdString pName = name;
294 pName = GetUniquePipeName();
296 CSingleLock lock(m_lock);
297 if (m_pipes.find(pName) != m_pipes.end())
300 XFILE::Pipe *p = new XFILE::Pipe(pName, nMaxPipeSize);
305 XFILE::Pipe *PipesManager::OpenPipe(const CStdString &name)
307 CSingleLock lock(m_lock);
308 if (m_pipes.find(name) == m_pipes.end())
310 m_pipes[name]->AddRef();
311 return m_pipes[name];
314 void PipesManager::ClosePipe(XFILE::Pipe *pipe)
316 CSingleLock lock(m_lock);
322 if (pipe->RefCount() == 0)
324 m_pipes.erase(pipe->GetName());
329 bool PipesManager::Exists(const CStdString &name)
331 CSingleLock lock(m_lock);
332 return (m_pipes.find(name) != m_pipes.end());