OverviewFilesCommitsIssuesDocsReleasesPeers

hyperswarm-peer / src / packet_queue.h

81 lines · c ref:
#ifndef HYPERSWARM_PACKET_QUEUE_H
#define HYPERSWARM_PACKET_QUEUE_H

#include <cstdint>
#include <cstring>
#include <deque>
#include <mutex>
#include <vector>

// Transfer mode matching Godot's MultiplayerPeer::TransferMode
enum PacketTransferMode {
	PACKET_UNRELIABLE = 0,
	PACKET_UNRELIABLE_ORDERED = 1,
	PACKET_RELIABLE = 2
};

struct Packet {
	std::vector<uint8_t> data;
	int32_t peer_id;
	int32_t channel;
	PacketTransferMode mode;

	Packet()
		: peer_id(0), channel(0), mode(PACKET_RELIABLE) {}

	Packet(const uint8_t *p_data, int32_t p_size, int32_t p_peer, int32_t p_channel, PacketTransferMode p_mode)
		: data(p_data, p_data + p_size), peer_id(p_peer), channel(p_channel), mode(p_mode) {}
};

// Thread-safe packet queue for passing data between the UDX network thread
// and Godot's main thread.
class PacketQueue {
public:
	void push(const Packet &pkt) {
		std::lock_guard<std::mutex> lock(_mutex);
		_queue.push_back(pkt);
	}

	void push(Packet &&pkt) {
		std::lock_guard<std::mutex> lock(_mutex);
		_queue.push_back(std::move(pkt));
	}

	bool pop(Packet &out) {
		std::lock_guard<std::mutex> lock(_mutex);
		if (_queue.empty()) return false;
		out = std::move(_queue.front());
		_queue.pop_front();
		return true;
	}

	// Peek without removing — used by _get_packet_peer() etc.
	bool peek(Packet &out) const {
		std::lock_guard<std::mutex> lock(_mutex);
		if (_queue.empty()) return false;
		out = _queue.front();
		return true;
	}

	int32_t size() const {
		std::lock_guard<std::mutex> lock(_mutex);
		return static_cast<int32_t>(_queue.size());
	}

	bool empty() const {
		std::lock_guard<std::mutex> lock(_mutex);
		return _queue.empty();
	}

	void clear() {
		std::lock_guard<std::mutex> lock(_mutex);
		_queue.clear();
	}

private:
	std::deque<Packet> _queue;
	mutable std::mutex _mutex;
};

#endif // HYPERSWARM_PACKET_QUEUE_H