Merge branch 'master' into jgrpp

# Conflicts:
#	src/CMakeLists.txt
#	src/network/network_server.cpp
#	src/network/network_survey.cpp
#	src/vehiclelist.cpp
This commit is contained in:
Jonathan G Rennison
2024-01-05 21:31:56 +00:00
20 changed files with 142 additions and 93 deletions

View File

@@ -281,10 +281,9 @@ void NetworkHTTPUninitialize()
{
_http_thread_exit = true;
/* Queues must be cleared (and the queue CV signalled) after _http_thread_exit is set to ensure that the HTTP thread can exit */
for (auto &callback : _http_callbacks) {
callback->ClearQueue();
}
/* Ensure the callbacks are handled. This is mostly needed as we send
* a survey just before close, and that might be pending here. */
NetworkHTTPSocketHandler::HTTPReceive();
{
std::lock_guard<std::mutex> lock(_http_mutex);

View File

@@ -96,20 +96,6 @@ public:
return this->queue.empty();
}
/**
* Clear everything in the queue.
*
* Should be called from the Game Thread.
*/
void ClearQueue()
{
std::lock_guard<std::mutex> lock(this->mutex);
this->queue.clear();
this->queue_cv.notify_all();
}
HTTPThreadSafeCallback(HTTPCallback *callback) : callback(callback) {}
~HTTPThreadSafeCallback()

View File

@@ -1854,30 +1854,25 @@ static void NetworkCheckRestartMap()
*/
static void NetworkAutoCleanCompanies()
{
bool clients_in_company[MAX_COMPANIES];
int vehicles_in_company[MAX_COMPANIES];
CompanyMask has_clients = 0;
CompanyMask has_vehicles = 0;
if (!_settings_client.network.autoclean_companies) return;
memset(clients_in_company, 0, sizeof(clients_in_company));
/* Detect the active companies */
for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
if (Company::IsValidID(ci->client_playas)) SetBit(has_clients, ci->client_playas);
}
if (!_network_dedicated) {
const NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(CLIENT_ID_SERVER);
assert(ci != nullptr);
if (Company::IsValidID(ci->client_playas)) clients_in_company[ci->client_playas] = true;
if (Company::IsValidID(ci->client_playas)) SetBit(has_clients, ci->client_playas);
}
if (_settings_client.network.autoclean_novehicles != 0) {
memset(vehicles_in_company, 0, sizeof(vehicles_in_company));
for (const Vehicle *v : Vehicle::Iterate()) {
if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle() || HasBit(v->subtype, GVSF_VIRTUAL)) continue;
vehicles_in_company[v->owner]++;
for (const Company *c : Company::Iterate()) {
if (std::any_of(std::begin(c->group_all), std::end(c->group_all), [](const GroupStatistics &gs) { return gs.num_vehicle != 0; })) SetBit(has_vehicles, c->index);
}
}
@@ -1886,7 +1881,7 @@ static void NetworkAutoCleanCompanies()
/* Skip the non-active once */
if (c->is_ai) continue;
if (!clients_in_company[c->index]) {
if (!HasBit(has_clients, c->index)) {
/* The company is empty for one month more */
_network_company_states[c->index].months_empty++;
@@ -1905,7 +1900,7 @@ static void NetworkAutoCleanCompanies()
NetworkServerUpdateCompanyPassworded(c->index, false);
}
/* Is the company empty for autoclean_novehicles-months, and has no vehicles? */
if (_settings_client.network.autoclean_novehicles != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_novehicles && vehicles_in_company[c->index] == 0) {
if (_settings_client.network.autoclean_novehicles != 0 && _network_company_states[c->index].months_empty > _settings_client.network.autoclean_novehicles && !HasBit(has_vehicles, c->index)) {
/* Shut the company down */
DoCommandP(0, CCA_DELETE | c->index << 16 | CRR_AUTOCLEAN << 24, 0, CMD_COMPANY_CTRL);
IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d with no vehicles", c->index + 1);

View File

@@ -10,6 +10,7 @@
#include "../stdafx.h"
#include "network_survey.h"
#include "network.h"
#include "network_func.h"
#include "network_internal.h"
#include "../company_base.h"
#include "../debug.h"
@@ -378,21 +379,29 @@ void NetworkSurveyHandler::Transmit(Reason reason, bool blocking)
if (blocking) {
std::unique_lock<std::mutex> lock(this->mutex);
/* Block no longer than 2 seconds. If we failed to send the survey in that time, so be it. */
this->loaded.wait_for(lock, std::chrono::seconds(2));
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now() + std::chrono::seconds(2);
while (!this->transmitted && std::chrono::steady_clock::now() < end) {
NetworkBackgroundLoop();
this->transmitted_cv.wait_for(lock, std::chrono::milliseconds(30));
}
}
}
void NetworkSurveyHandler::OnFailure()
{
Debug(net, 1, "Survey: failed to send survey results");
this->loaded.notify_all();
this->transmitted = true;
this->transmitted_cv.notify_all();
}
void NetworkSurveyHandler::OnReceiveData(UniqueBuffer<char> data)
{
if (data == nullptr) {
Debug(net, 1, "Survey: survey results sent");
this->loaded.notify_all();
this->transmitted = true;
this->transmitted_cv.notify_all();
}
}

View File

@@ -46,7 +46,8 @@ public:
private:
std::mutex mutex; ///< Mutex for the condition variable.
std::condition_variable loaded; ///< Condition variable to wait for the survey to be sent.
std::atomic<bool> transmitted; ///< Whether the survey has been transmitted.
std::condition_variable transmitted_cv; ///< Condition variable to inform changes to transmitted.
};
extern NetworkSurveyHandler _survey;