1/* This file is part of the KDE project
2 Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17
18*/
19
20#include "packetpool.h"
21#include "packetpool_p.h"
22#include "packet.h"
23#include "packet_p.h"
24
25namespace Phonon
26{
27
28int PacketPool::packetSize() const { return d_ptr->packetSize; }
29int PacketPool::poolSize() const { return d_ptr->poolSize; }
30int PacketPool::unusedPackets() const { return d_ptr->ringBufferSize.loadAcquire(); }
31
32PacketPoolPrivate::PacketPoolPrivate(int _packetSize, int _poolSize)
33 : freePackets(new PacketPrivate *[_poolSize]),
34 packetMemory(new char[_packetSize * _poolSize]),
35 readPosition(0), writePosition(0),
36 ringBufferSize(_poolSize),
37 packetSize(_packetSize),
38 poolSize(_poolSize)
39{
40 for (int i = 0; i < _poolSize; ++i) {
41 freePackets[i] = new PacketPrivate(&packetMemory[i * packetSize], this);
42 }
43}
44
45PacketPoolPrivate::~PacketPoolPrivate()
46{
47 Q_ASSERT(poolSize == ringBufferSize.loadAcquire());
48 for (int i = 0; i < poolSize; ++i) {
49 delete freePackets[i];
50 }
51 delete[] freePackets;
52 delete[] packetMemory;
53}
54
55void PacketPoolPrivate::releasePacket(const Packet &packet)
56{
57 const int _writePos = writePosition.fetchAndAddAcquire(valueToAdd: 1);
58 int pos = _writePos;
59 while (pos >= poolSize) {
60 pos -= poolSize;
61 }
62 writePosition.testAndSetRelease(expectedValue: _writePos, newValue: pos);
63 freePackets[pos] = packet.d_ptr;
64 ringBufferSize.ref();
65}
66
67Packet PacketPoolPrivate::acquirePacket()
68{
69 const int s = ringBufferSize.fetchAndAddRelaxed(valueToAdd: -1);
70 if (s <= 0) {
71 ringBufferSize.fetchAndAddRelaxed(valueToAdd: 1);
72 return Packet();
73 }
74 const int _readPos = readPosition.fetchAndAddRelaxed(valueToAdd: 1);
75 int pos = _readPos;
76 while (pos >= poolSize) {
77 pos -= poolSize;
78 }
79 readPosition.testAndSetRelease(expectedValue: _readPos, newValue: pos);
80 freePackets[pos]->m_size = 0;
81 return Packet(*freePackets[pos]);
82}
83
84PacketPool::PacketPool(int packetSize, int _poolSize)
85 : d_ptr(new PacketPoolPrivate(packetSize, _poolSize))
86{
87 d_ptr->ref.ref();
88}
89
90PacketPool::PacketPool(const PacketPool &rhs)
91 : d_ptr(rhs.d_ptr)
92{
93 d_ptr->ref.ref();
94}
95
96PacketPool &PacketPool::operator=(const PacketPool &rhs)
97{
98 if (d_ptr != rhs.d_ptr) {
99 if (!d_ptr->ref.deref()) {
100 delete d_ptr;
101 }
102 d_ptr = rhs.d_ptr;
103 d_ptr->ref.ref();
104 }
105 return *this;
106}
107
108PacketPool::~PacketPool()
109{
110 if (!d_ptr->ref.deref()) {
111 delete d_ptr;
112 }
113}
114
115} // namespace Phonon
116

source code of phonon/phonon/experimental/packetpool.cpp