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