Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Toggle main menu visibility
Loading...
Searching...
No Matches
BoostAsioWriteQueue.h
Go to the documentation of this file.
1
/*
2
* This file is part of Project SkyFire https://www.projectskyfire.org.
3
* See LICENSE.md file for Copyright information
4
*/
5
6
#ifndef SF_BOOSTASIOWRITEQUEUE_H
7
#define SF_BOOSTASIOWRITEQUEUE_H
8
9
#include <boost/asio/bind_executor.hpp>
10
#include <boost/asio/buffer.hpp>
11
#include <boost/asio/post.hpp>
12
#include <boost/asio/strand.hpp>
13
#include <boost/asio/write.hpp>
14
#include <boost/system/error_code.hpp>
15
#include <atomic>
16
#include <deque>
17
#include <functional>
18
#include <vector>
19
20
namespace
Skyfire
21
{
22
namespace
Net
23
{
24
template
<
class
AsyncWriteStream>
25
class
BoostAsioWriteQueue
26
{
27
public
:
28
typedef
std::function<void(boost::system::error_code
const
&,
size_t
)>
CompletionHandler
;
29
30
explicit
BoostAsioWriteQueue
(AsyncWriteStream& stream) :
31
_stream
(stream),
32
_strand
(boost::asio::make_strand(stream.get_executor())),
33
_queue
(),
34
_pendingBytes
(0),
35
_writeInProgress
(false)
36
{
37
}
38
39
bool
HasPendingOutput
()
const
40
{
41
return
_pendingBytes
.load(std::memory_order_acquire) != 0;
42
}
43
44
void
Queue
(std::vector<char> data,
CompletionHandler
handler)
45
{
46
if
(data.empty())
47
{
48
boost::asio::post(
_strand
,
49
[handler = std::move(handler)]()
mutable
50
{
51
if
(handler)
52
handler(boost::system::error_code(), 0);
53
});
54
return
;
55
}
56
57
_pendingBytes
.fetch_add(data.size(), std::memory_order_acq_rel);
58
boost::asio::post(
_strand
,
59
[
this
, data = std::move(data), handler = std::move(handler)]()
mutable
60
{
61
bool
startWrite = !
_writeInProgress
&&
_queue
.empty();
62
_queue
.push_back(
Entry
(std::move(data), std::move(handler)));
63
64
if
(startWrite)
65
StartWrite
();
66
});
67
}
68
69
private
:
70
struct
Entry
71
{
72
Entry
(std::vector<char> data,
CompletionHandler
handler) :
73
Data
(std::move(data)),
74
Handler
(std::move(handler))
75
{
76
}
77
78
std::vector<char>
Data
;
79
CompletionHandler
Handler
;
80
};
81
82
void
StartWrite
()
83
{
84
if
(
_queue
.empty())
85
{
86
_writeInProgress
=
false
;
87
return
;
88
}
89
90
_writeInProgress
=
true
;
91
boost::asio::async_write(
_stream
, boost::asio::buffer(
_queue
.front().Data),
92
boost::asio::bind_executor(
_strand
,
93
[
this
](boost::system::error_code
const
& error,
size_t
transferredBytes)
94
{
95
HandleWrite(error, transferredBytes);
96
}));
97
}
98
99
void
HandleWrite
(boost::system::error_code
const
& error,
size_t
transferredBytes)
100
{
101
if
(
_queue
.empty())
102
{
103
_writeInProgress
=
false
;
104
return
;
105
}
106
107
Entry
completed(std::move(
_queue
.front()));
108
_queue
.pop_front();
109
SubtractPending
(completed.
Data
.size());
110
_writeInProgress
=
false
;
111
112
if
(completed.
Handler
)
113
completed.
Handler
(error, transferredBytes);
114
115
if
(error)
116
{
117
FailQueued
(error);
118
return
;
119
}
120
121
StartWrite
();
122
}
123
124
void
FailQueued
(boost::system::error_code
const
& error)
125
{
126
while
(!
_queue
.empty())
127
{
128
Entry
entry(std::move(
_queue
.front()));
129
_queue
.pop_front();
130
SubtractPending
(entry.
Data
.size());
131
132
if
(entry.
Handler
)
133
entry.
Handler
(error, 0);
134
}
135
}
136
137
void
SubtractPending
(
size_t
bytes)
138
{
139
_pendingBytes
.fetch_sub(bytes, std::memory_order_acq_rel);
140
}
141
142
AsyncWriteStream&
_stream
;
143
boost::asio::strand<typename AsyncWriteStream::executor_type>
_strand
;
144
std::deque<Entry>
_queue
;
145
std::atomic<size_t>
_pendingBytes
;
146
bool
_writeInProgress
;
147
};
148
}
149
}
150
151
#endif
Entry
Entry
Definition
boss_headless_horseman.cpp:38
Skyfire::Net::BoostAsioWriteQueue::StartWrite
void StartWrite()
Definition
BoostAsioWriteQueue.h:82
Skyfire::Net::BoostAsioWriteQueue::CompletionHandler
std::function< void(boost::system::error_code const &, size_t)> CompletionHandler
Definition
BoostAsioWriteQueue.h:28
Skyfire::Net::BoostAsioWriteQueue::_pendingBytes
std::atomic< size_t > _pendingBytes
Definition
BoostAsioWriteQueue.h:145
Skyfire::Net::BoostAsioWriteQueue::BoostAsioWriteQueue
BoostAsioWriteQueue(AsyncWriteStream &stream)
Definition
BoostAsioWriteQueue.h:30
Skyfire::Net::BoostAsioWriteQueue::HandleWrite
void HandleWrite(boost::system::error_code const &error, size_t transferredBytes)
Definition
BoostAsioWriteQueue.h:99
Skyfire::Net::BoostAsioWriteQueue::_writeInProgress
bool _writeInProgress
Definition
BoostAsioWriteQueue.h:146
Skyfire::Net::BoostAsioWriteQueue::Queue
void Queue(std::vector< char > data, CompletionHandler handler)
Definition
BoostAsioWriteQueue.h:44
Skyfire::Net::BoostAsioWriteQueue::_queue
std::deque< Entry > _queue
Definition
BoostAsioWriteQueue.h:144
Skyfire::Net::BoostAsioWriteQueue::FailQueued
void FailQueued(boost::system::error_code const &error)
Definition
BoostAsioWriteQueue.h:124
Skyfire::Net::BoostAsioWriteQueue::_stream
AsyncWriteStream & _stream
Definition
BoostAsioWriteQueue.h:142
Skyfire::Net::BoostAsioWriteQueue::HasPendingOutput
bool HasPendingOutput() const
Definition
BoostAsioWriteQueue.h:39
Skyfire::Net::BoostAsioWriteQueue::_strand
boost::asio::strand< typename AsyncWriteStream::executor_type > _strand
Definition
BoostAsioWriteQueue.h:143
Skyfire::Net::BoostAsioWriteQueue::SubtractPending
void SubtractPending(size_t bytes)
Definition
BoostAsioWriteQueue.h:137
Skyfire::Net
Definition
WorldSocket.h:36
Skyfire
Definition
AuthPatchTransfer.h:12
Skyfire::Net::BoostAsioWriteQueue::Entry
Definition
BoostAsioWriteQueue.h:71
Skyfire::Net::BoostAsioWriteQueue::Entry::Data
std::vector< char > Data
Definition
BoostAsioWriteQueue.h:78
Skyfire::Net::BoostAsioWriteQueue::Entry::Handler
CompletionHandler Handler
Definition
BoostAsioWriteQueue.h:79
Skyfire::Net::BoostAsioWriteQueue::Entry::Entry
Entry(std::vector< char > data, CompletionHandler handler)
Definition
BoostAsioWriteQueue.h:72
src
server
shared
Network
BoostAsioWriteQueue.h
Generated on
for Project SkyFire Core by
1.17.0