<commit_before>#include "AsioTcpSocket.hpp"
#include "AsioService.hpp"
#include "../MemoryFile.hpp"
#include "../PartFile.hpp"
#include "../CriticalCode.hpp"
#include <boost/bind.hpp>

const size_t AsioTcpSocket::receiveFileSize = 0x1000;

AsioTcpSocket::SendItem::SendItem(ptr<File> data, ptr<SendHandler> handler)
: data(data), handler(handler) {}

/// Вспомогательный класс последовательности буферов.
/** Удовлетворяет требованиям Asio к ConstBufferSequence. */
class AsioTcpSocket::Buffers
{
private:
	typedef std::deque<SendItem>::const_iterator InternalIterator;

public:
	/// Класс буфера.
	class Buffer
	{
	private:
		/// Файл с данными.
		ptr<File> file;
		/// Смещение от начала, которое нужно пропустить.
		size_t skip;

	public:
		Buffer(ptr<File> file, size_t skip) : file(file), skip(skip) {}

		operator boost::asio::const_buffer() const
		{
			return boost::asio::const_buffer((const void*)*this, (size_t)*this);
		}

		operator const void*() const
		{
			return (const char*)file->GetData() + skip;
		}

		operator size_t() const
		{
			return file->GetSize() - skip;
		}
	};

	typedef Buffer value_type;

	/// Класс константного итератора.
	class ConstIterator
	{
	private:
		const Buffers& buffers;
		InternalIterator it;

	public:
		ConstIterator(const Buffers& buffers, InternalIterator it) : buffers(buffers), it(it) {}

		const Buffer operator*() const
		{
			return Buffer(it->data, it == buffers.beginIt ? buffers.firstSkip : 0);
		}
		ConstIterator& operator++()
		{
			++it;
			return *this;
		}
		ConstIterator operator++(int)
		{
			ConstIterator temp(*this);
			++it;
			return temp;
		}
		ConstIterator& operator--()
		{
			--it;
			return *this;
		}
		ConstIterator operator--(int)
		{
			ConstIterator temp(*this);
			--it;
			return temp;
		}
		friend bool operator==(const ConstIterator& a, const ConstIterator& b)
		{
			return a.it == b.it;
		}
		friend bool operator!=(const ConstIterator& a, const ConstIterator& b)
		{
			return a.it != b.it;
		}
	};

	typedef ConstIterator const_iterator;

private:
	// Границы посылки.
	InternalIterator beginIt, endIt;
	/// Сколько следует пропустить от начала первого буфера.
	size_t firstSkip;

public:
	Buffers(InternalIterator begin, InternalIterator end, size_t firstSkip)
	: beginIt(begin), endIt(end), firstSkip(firstSkip) {}

	ConstIterator begin() const
	{
		return ConstIterator(*this, beginIt);
	}
	ConstIterator end() const
	{
		return ConstIterator(*this, endIt);
	}
};

AsioTcpSocket::AsioTcpSocket(ptr<AsioService> service)
	: service(service), socket(service->GetIoService()),
	firstItemSent(0), sendClosed(false) {}

boost::asio::ip::tcp::socket& AsioTcpSocket::GetSocket()
{
	return socket;
}

void AsioTcpSocket::StartSending()
{
	CriticalCode cc(sendQueueCS);

	// если в очереди ничего нет, проверить, не закрыт ли сокет
	if(sendQueue.empty())
	{
		if(sendClosed)
			try
			{
				socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
			}
			catch(boost::system::error_code error)
			{
				THROW_SECONDARY_EXCEPTION("Can't close Asio TCP socket", AsioService::ConvertError(error));
			}
	}
	else
	{
		// очередь не пуста, начинаем отправку
		socket.async_write_some(Buffers(sendQueue.begin(), sendQueue.end(), firstItemSent),
			boost::bind(&AsioTcpSocket::Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
	}
}

void AsioTcpSocket::Sent(const boost::system::error_code& error, size_t transferred)
{<commit_msg>fix for double entering critical section<commit_after>#include "AsioTcpSocket.hpp"
#include "AsioService.hpp"
#include "../MemoryFile.hpp"
#include "../PartFile.hpp"
#include "../CriticalCode.hpp"
#include <boost/bind.hpp>

const size_t AsioTcpSocket::receiveFileSize = 0x1000;

AsioTcpSocket::SendItem::SendItem(ptr<File> data, ptr<SendHandler> handler)
: data(data), handler(handler) {}

/// Вспомогательный класс последовательности буферов.
/** Удовлетворяет требованиям Asio к ConstBufferSequence. */
class AsioTcpSocket::Buffers
{
private:
	typedef std::deque<SendItem>::const_iterator InternalIterator;

public:
	/// Класс буфера.
	class Buffer
	{
	private:
		/// Файл с данными.
		ptr<File> file;
		/// Смещение от начала, которое нужно пропустить.
		size_t skip;

	public:
		Buffer(ptr<File> file, size_t skip) : file(file), skip(skip) {}

		operator boost::asio::const_buffer() const
		{
			return boost::asio::const_buffer((const void*)*this, (size_t)*this);
		}

		operator const void*() const
		{
			return (const char*)file->GetData() + skip;
		}

		operator size_t() const
		{
			return file->GetSize() - skip;
		}
	};

	typedef Buffer value_type;

	/// Класс константного итератора.
	class ConstIterator
	{
	private:
		const Buffers& buffers;
		InternalIterator it;

	public:
		ConstIterator(const Buffers& buffers, InternalIterator it) : buffers(buffers), it(it) {}

		const Buffer operator*() const
		{
			return Buffer(it->data, it == buffers.beginIt ? buffers.firstSkip : 0);
		}
		ConstIterator& operator++()
		{
			++it;
			return *this;
		}
		ConstIterator operator++(int)
		{
			ConstIterator temp(*this);
			++it;
			return temp;
		}
		ConstIterator& operator--()
		{
			--it;
			return *this;
		}
		ConstIterator operator--(int)
		{
			ConstIterator temp(*this);
			--it;
			return temp;
		}
		friend bool operator==(const ConstIterator& a, const ConstIterator& b)
		{
			return a.it == b.it;
		}
		friend bool operator!=(const ConstIterator& a, const ConstIterator& b)
		{
			return a.it != b.it;
		}
	};

	typedef ConstIterator const_iterator;

private:
	// Границы посылки.
	InternalIterator beginIt, endIt;
	/// Сколько следует пропустить от начала первого буфера.
	size_t firstSkip;

public:
	Buffers(InternalIterator begin, InternalIterator end, size_t firstSkip)
	: beginIt(begin), endIt(end), firstSkip(firstSkip) {}

	ConstIterator begin() const
	{
		return ConstIterator(*this, beginIt);
	}
	ConstIterator end() const
	{
		return ConstIterator(*this, endIt);
	}
};

AsioTcpSocket::AsioTcpSocket(ptr<AsioService> service)
	: service(service), socket(service->GetIoService()),
	firstItemSent(0), sendClosed(false) {}

boost::asio::ip::tcp::socket& AsioTcpSocket::GetSocket()
{
	return socket;
}

void AsioTcpSocket::StartSending()
{
	// если в очереди ничего нет, проверить, не закрыт ли сокет
	if(sendQueue.empty())
	{
		if(sendClosed)
			try
			{
				socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
			}
			catch(boost::system::error_code error)
			{
				THROW_SECONDARY_EXCEPTION("Can't close Asio TCP socket", AsioService::ConvertError(error));
			}
	}
	else
	{
		// очередь не пуста, начинаем отправку
		socket.async_write_some(Buffers(sendQueue.begin(), sendQueue.end(), firstItemSent),
			boost::bind(&AsioTcpSocket::Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
	}
}

void AsioTcpSocket::Sent(const boost::system::error_code& error, size_t transferred)
{
{'fraction_non_alphanumeric': 0.139471021823963, 'fraction_numerical': 0.0020234137881196706, 'mean_word_length': 4.536, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7110920', 'n_tokens_mistral': 2687, 'n_tokens_neox': 2497, 'n_words': 517}