Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use std::vector instead of bespoke Array class #7

Merged
merged 4 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if(LIBUTP_STANDALONE_BUILD)
endif()

if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 98)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
Expand Down
2 changes: 2 additions & 0 deletions utp_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* THE SOFTWARE.
*/

#include <assert.h>

#include "utp_hash.h"
#include "utp_types.h"

Expand Down
60 changes: 28 additions & 32 deletions utp_internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,21 +667,22 @@ struct UTPSocket {
size_t get_packet_size() const;
};

void removeSocketFromAckList(UTPSocket *conn)
static void removeSocketFromAckList(UTPSocket *conn)
{
if (conn->ida >= 0)
{
UTPSocket *last = conn->ctx->ack_sockets[conn->ctx->ack_sockets.GetCount() - 1];
auto const ida = conn->ida;
if (ida < 0)
return;

assert(last->ida < (int)(conn->ctx->ack_sockets.GetCount()));
assert(conn->ctx->ack_sockets[last->ida] == last);
last->ida = conn->ida;
conn->ctx->ack_sockets[conn->ida] = last;
conn->ida = -1;
auto& acks = conn->ctx->ack_sockets;
assert(acks[ida]->ida == ida);

// Decrease the count
conn->ctx->ack_sockets.SetCount(conn->ctx->ack_sockets.GetCount() - 1);
}
// fast-remove `conn` from acks by swapping w/last and resizing.
// update `ida` index for both swapped sockets.
// note the steps need to be safe even when conn == acks.back()
std::swap(acks[ida], acks.back());
acks[ida]->ida = ida;
acks.resize(acks.size() - 1U);
conn->ida = -1;
}

static void utp_register_sent_packet(utp_context *ctx, size_t length)
Expand Down Expand Up @@ -715,7 +716,8 @@ void UTPSocket::schedule_ack()
#if UTP_DEBUG_LOGGING
log(UTP_LOG_DEBUG, "schedule_ack");
#endif
ida = ctx->ack_sockets.Append(this);
ida = ctx->ack_sockets.size();
ctx->ack_sockets.push_back(this);
} else {
#if UTP_DEBUG_LOGGING
log(UTP_LOG_DEBUG, "schedule_ack: already in list");
Expand Down Expand Up @@ -2923,12 +2925,9 @@ int utp_process_udp(utp_context *ctx, const byte *buffer, size_t len, const stru
if (flags != ST_SYN) {
ctx->current_ms = utp_call_get_milliseconds(ctx, NULL);

for (size_t i = 0; i < ctx->rst_info.GetCount(); i++) {
if ((ctx->rst_info[i].connid == id) &&
(ctx->rst_info[i].addr == addr) &&
(ctx->rst_info[i].ack_nr == seq_nr))
{
ctx->rst_info[i].timestamp = ctx->current_ms;
for (auto& info : ctx->rst_info) {
if ((info.connid == id) && (info.addr == addr) && (info.ack_nr == seq_nr)) {
info.timestamp = ctx->current_ms;

#if UTP_DEBUG_LOGGING
ctx->log(UTP_LOG_DEBUG, NULL, "recv not sending RST to non-SYN (stored)");
Expand All @@ -2938,7 +2937,7 @@ int utp_process_udp(utp_context *ctx, const byte *buffer, size_t len, const stru
}
}

if (ctx->rst_info.GetCount() > RST_INFO_LIMIT) {
if (ctx->rst_info.size() > RST_INFO_LIMIT) {

#if UTP_DEBUG_LOGGING
ctx->log(UTP_LOG_DEBUG, NULL, "recv not sending RST to non-SYN (limit at %u stored)", (uint)ctx->rst_info.GetCount());
Expand All @@ -2951,11 +2950,7 @@ int utp_process_udp(utp_context *ctx, const byte *buffer, size_t len, const stru
ctx->log(UTP_LOG_DEBUG, NULL, "recv send RST to non-SYN (%u stored)", (uint)ctx->rst_info.GetCount());
#endif

RST_Info &r = ctx->rst_info.Append();
r.addr = addr;
r.connid = id;
r.ack_nr = seq_nr;
r.timestamp = ctx->current_ms;
ctx->rst_info.emplace_back(addr, id, seq_nr, ctx->current_ms);

UTPSocket::send_rst(ctx, addr, id, seq_nr, utp_call_get_random(ctx, NULL));
return 1;
Expand Down Expand Up @@ -3280,7 +3275,7 @@ void utp_issue_deferred_acks(utp_context *ctx)
assert(ctx);
if (!ctx) return;

for (size_t i = 0; i < ctx->ack_sockets.GetCount(); i++) {
for (size_t i = 0; i < ctx->ack_sockets.size(); i++) {
UTPSocket *conn = ctx->ack_sockets[i];
conn->send_ack();
i--;
Expand All @@ -3300,15 +3295,16 @@ void utp_check_timeouts(utp_context *ctx)

ctx->last_check = ctx->current_ms;

for (size_t i = 0; i < ctx->rst_info.GetCount(); i++) {
if ((int)(ctx->current_ms - ctx->rst_info[i].timestamp) >= RST_INFO_TIMEOUT) {
ctx->rst_info.MoveUpLast(i);
auto& infos = ctx->rst_info;
for (size_t i = 0; i < infos.size(); i++) {
if ((int)(ctx->current_ms - infos[i].timestamp) >= RST_INFO_TIMEOUT) {
// fast-remove from `infos` by swapping w/last and resizing
std::swap(infos[i], infos.back());
infos.resize(infos.size() - 1U);
i--;
}
}
if (ctx->rst_info.GetCount() != ctx->rst_info.GetAlloc()) {
ctx->rst_info.Compact();
}
infos.shrink_to_fit();

utp_hash_iterator_t it;
UTPSocketKeyData* keyData;
Expand Down
16 changes: 14 additions & 2 deletions utp_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <assert.h>
#include <stdio.h>

#include <vector>

#include "utp.h"
#include "utp_callbacks.h"
#include "utp_templates.h"
Expand Down Expand Up @@ -59,6 +61,16 @@ enum bandwidth_type_t {
#endif

struct PACKED_ATTRIBUTE RST_Info {
RST_Info() = default;

RST_Info(PackedSockAddr _addr, uint32 _connid, uint16 _ack_nr, uint64 _timestamp)
: addr{ _addr }
, connid{ _connid }
, ack_nr{ _ack_nr }
, timestamp{ _timestamp }
{
}

PackedSockAddr addr;
uint32 connid;
uint16 ack_nr;
Expand Down Expand Up @@ -117,8 +129,8 @@ struct struct_utp_context {
uint64 current_ms;
utp_context_stats context_stats;
UTPSocket *last_utp_socket;
Array<UTPSocket*> ack_sockets;
Array<RST_Info> rst_info;
std::vector<UTPSocket*> ack_sockets;
std::vector<RST_Info> rst_info;
UTPSocketHT *utp_sockets;
size_t target_delay;
size_t opt_sndbuf;
Expand Down
98 changes: 0 additions & 98 deletions utp_templates.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#define __TEMPLATES_H__

#include "utp_types.h"
#include <assert.h>

#if defined(POSIX)
/* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo
Expand Down Expand Up @@ -95,101 +94,4 @@ typedef big_endian<uint16> uint16_big;

template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); }

typedef int SortCompareProc(const void *, const void *);

template<typename T> static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); }


// WARNING: The template parameter MUST be a POD type!
template <typename T, size_t minsize = 16> class Array {
protected:
T *mem;
size_t alloc,count;

public:
Array(size_t init) { Init(init); }
Array() { Init(); }
~Array() { Free(); }

void inline Init() { mem = NULL; alloc = count = 0; }
void inline Init(size_t init) { Init(); if (init) Resize(init); }
size_t inline GetCount() const { return count; }
size_t inline GetAlloc() const { return alloc; }
void inline SetCount(size_t c) { count = c; }

inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; }
inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; }

void inline Resize(size_t a) {
if (a == 0) { free(mem); Init(); }
else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); }
}

void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); }

inline size_t Append(const T &t) {
if (count >= alloc) Grow();
size_t r=count++;
mem[r] = t;
return r;
}

T inline &Append() {
if (count >= alloc) Grow();
return mem[count++];
}

void inline Compact() {
Resize(count);
}

void inline Free() {
free(mem);
Init();
}

void inline Clear() {
count = 0;
}

bool inline MoveUpLast(size_t index) {
assert(index < count);
size_t c = --count;
if (index != c) {
mem[index] = mem[c];
return true;
}
return false;
}

bool inline MoveUpLastExist(const T &v) {
return MoveUpLast(LookupElementExist(v));
}

size_t inline LookupElement(const T &v) const {
for(size_t i = 0; i != count; i++)
if (mem[i] == v)
return i;
return (size_t) -1;
}

bool inline HasElement(const T &v) const {
return LookupElement(v) != -1;
}

typedef int SortCompareProc(const T *a, const T *b);

void Sort(SortCompareProc* proc, size_t start, size_t end) {
QuickSortT(&mem[start], end - start, proc);
}

void Sort(SortCompareProc* proc, size_t start) {
Sort(proc, start, count);
}

void Sort(SortCompareProc* proc) {
Sort(proc, 0, count);
}
};

#endif //__TEMPLATES_H__