diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp new file mode 100644 index 0000000000..af19162bb8 --- /dev/null +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -0,0 +1,82 @@ +// +// SendQueue.cpp +// libraries/networking/src/udt +// +// Created by Clement on 7/21/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SendQueue.h" + +#include +#include + +#include + +namespace udt { + +std::unique_ptr SendQueue::create() { + return std::unique_ptr(new SendQueue()); +} + +SendQueue::SendQueue() { + _sendTimer.reset(new QTimer(this)); + _sendTimer->setSingleShot(true); + QObject::connect(_sendTimer.get(), &QTimer::timeout, this, &SendQueue::sendNextPacket); + + _packetSendPeriod = DEFAULT_SEND_PERIOD; + _lastSendTimestamp = 0; +} + +void SendQueue::queuePacket(std::unique_ptr packet) { + QWriteLocker locker(&_packetsLock); + _packets.push_back(std::move(packet)); +} + +void SendQueue::start() { + // We need to make sure this is called on the right thread + if (thread() != QThread::currentThread()) { + QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection); + } + // This will send a packet and fire the send timer + sendNextPacket(); +} + +void SendQueue::stop() { + // We need to make sure this is called on the right thread + if (thread() != QThread::currentThread()) { + QMetaObject::invokeMethod(this, "stop", Qt::QueuedConnection); + } + // Stopping the timer will stop the sending of packets + _sendTimer->stop(); +} + +void SendQueue::sendNextPacket() { + // Record timing + auto sendTime = msecTimestampNow(); // msec + _lastSendTimestamp = sendTime; + // TODO send packet + + // Insert the packet we have just sent in the sent list + _sentPackets[_nextPacket->readSequenceNumber()].swap(_nextPacket); + Q_ASSERT(!_nextPacket); // There should be no packet where we inserted + + { // Grab next packet to be sent + QWriteLocker locker(&_packetsLock); + _nextPacket.swap(_packets.front()); + _packets.pop_front(); + } + + // How long before next packet send + auto timeToSleep = (sendTime + _packetSendPeriod) - msecTimestampNow(); // msec + if (timeToSleep > 0) { + _sendTimer->start(timeToSleep); + } else { + _sendTimer->start(0); + } +} + +} diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h new file mode 100644 index 0000000000..9767cfe7aa --- /dev/null +++ b/libraries/networking/src/udt/SendQueue.h @@ -0,0 +1,68 @@ +// +// SendQueue.h +// libraries/networking/src/udt +// +// Created by Clement on 7/21/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SendQueue_h +#define hifi_SendQueue_h + +#include +#include + +#include +#include + +#include "Packet.h" + +class QTimer; + +namespace udt { + +class SendQueue : public QObject { + Q_OBJECT + +public: + static const int DEFAULT_SEND_PERIOD = 16; // msec + + static std::unique_ptr create(); + + void queuePacket(std::unique_ptr packet); + int getQueueSize() const { return _packets.size(); } + + quint64 getLastSendTimestamp() const { return _lastSendTimestamp; } + + int getPacketSendPeriod() const { return _packetSendPeriod; } + void setPacketSendPeriod(int newPeriod) { _packetSendPeriod = newPeriod; } + +public slots: + void start(); + void stop(); + +private slots: + void sendNextPacket(); + +private: + SendQueue(); + SendQueue(SendQueue& other) = delete; + SendQueue(SendQueue&& other) = delete; + + QReadWriteLock _packetsLock; // Protects the packets to be sent list. + std::list> _packets; // List of packets to be sent + std::unique_ptr _nextPacket; + + std::unique_ptr _sendTimer; // Send timer + std::atomic _packetSendPeriod; // Interval between two packet send envent in msec + std::atomic _lastSendTimestamp; // Record last time of packet departure + + std::unordered_map> _sentPackets; // Packets waiting for ACK. +}; + +} + +#endif // hifi_SendQueue_h