File indexing completed on 2024-05-05 04:44:41

0001 /*  This file is part of the KDE project
0002     Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Library General Public
0006     License version 2 as published by the Free Software Foundation.
0007 
0008     This library is distributed in the hope that it will be useful,
0009     but WITHOUT ANY WARRANTY; without even the implied warranty of
0010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0011     Library General Public License for more details.
0012 
0013     You should have received a copy of the GNU Library General Public License
0014     along with this library; see the file COPYING.LIB.  If not, write to
0015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0016     Boston, MA 02110-1301, USA.
0017 
0018 */
0019 
0020 #include "packetpool.h"
0021 #include "packetpool_p.h"
0022 #include "packet.h"
0023 #include "packet_p.h"
0024 
0025 namespace Phonon
0026 {
0027 
0028 int PacketPool::packetSize() const { return d_ptr->packetSize; }
0029 int PacketPool::poolSize() const { return d_ptr->poolSize; }
0030 int PacketPool::unusedPackets() const { return d_ptr->ringBufferSize.loadAcquire(); }
0031 
0032 PacketPoolPrivate::PacketPoolPrivate(int _packetSize, int _poolSize)
0033     : freePackets(new PacketPrivate *[_poolSize]),
0034     packetMemory(new char[_packetSize * _poolSize]),
0035     readPosition(0), writePosition(0),
0036     ringBufferSize(_poolSize),
0037     packetSize(_packetSize),
0038     poolSize(_poolSize)
0039 {
0040     for (int i = 0; i < _poolSize; ++i) {
0041         freePackets[i] = new PacketPrivate(&packetMemory[i * packetSize], this);
0042     }
0043 }
0044 
0045 PacketPoolPrivate::~PacketPoolPrivate()
0046 {
0047     Q_ASSERT(poolSize == ringBufferSize.loadAcquire());
0048     for (int i = 0; i < poolSize; ++i) {
0049         delete freePackets[i];
0050     }
0051     delete[] freePackets;
0052     delete[] packetMemory;
0053 }
0054 
0055 void PacketPoolPrivate::releasePacket(const Packet &packet)
0056 {
0057     const int _writePos = writePosition.fetchAndAddAcquire(1);
0058     int pos = _writePos;
0059     while (pos >= poolSize) {
0060         pos -= poolSize;
0061     }
0062     writePosition.testAndSetRelease(_writePos, pos);
0063     freePackets[pos] = packet.d_ptr;
0064     ringBufferSize.ref();
0065 }
0066 
0067 Packet PacketPoolPrivate::acquirePacket()
0068 {
0069     const int s = ringBufferSize.fetchAndAddRelaxed(-1);
0070     if (s <= 0) {
0071         ringBufferSize.fetchAndAddRelaxed(1);
0072         return Packet();
0073     }
0074     const int _readPos = readPosition.fetchAndAddRelaxed(1);
0075     int pos = _readPos;
0076     while (pos >= poolSize) {
0077         pos -= poolSize;
0078     }
0079     readPosition.testAndSetRelease(_readPos, pos);
0080     freePackets[pos]->m_size = 0;
0081     return Packet(*freePackets[pos]);
0082 }
0083 
0084 PacketPool::PacketPool(int packetSize, int _poolSize)
0085     : d_ptr(new PacketPoolPrivate(packetSize, _poolSize))
0086 {
0087     d_ptr->ref.ref();
0088 }
0089 
0090 PacketPool::PacketPool(const PacketPool &rhs)
0091     : d_ptr(rhs.d_ptr)
0092 {
0093     d_ptr->ref.ref();
0094 }
0095 
0096 PacketPool &PacketPool::operator=(const PacketPool &rhs)
0097 {
0098     if (d_ptr != rhs.d_ptr) {
0099         if (!d_ptr->ref.deref()) {
0100             delete d_ptr;
0101         }
0102         d_ptr = rhs.d_ptr;
0103         d_ptr->ref.ref();
0104     }
0105     return *this;
0106 }
0107 
0108 PacketPool::~PacketPool()
0109 {
0110     if (!d_ptr->ref.deref()) {
0111         delete d_ptr;
0112     }
0113 }
0114 
0115 } // namespace Phonon