Merge d46fc495ff
into c4d624083d
This commit is contained in:
commit
0d7a7a3ae5
@ -51,6 +51,7 @@
|
|||||||
#include "translation.h"
|
#include "translation.h"
|
||||||
#include "content/mod_configuration.h"
|
#include "content/mod_configuration.h"
|
||||||
#include "mapnode.h"
|
#include "mapnode.h"
|
||||||
|
#include "script/sscsm_controller.h"
|
||||||
|
|
||||||
extern gui::IGUIEnvironment* guienv;
|
extern gui::IGUIEnvironment* guienv;
|
||||||
|
|
||||||
@ -131,6 +132,8 @@ Client::Client(
|
|||||||
|
|
||||||
m_cache_save_interval = g_settings->getU16("server_map_save_interval");
|
m_cache_save_interval = g_settings->getU16("server_map_save_interval");
|
||||||
m_mesh_grid = { g_settings->getU16("client_mesh_chunk") };
|
m_mesh_grid = { g_settings->getU16("client_mesh_chunk") };
|
||||||
|
|
||||||
|
m_sscsm_controller = SSCSMController::create();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::migrateModStorage()
|
void Client::migrateModStorage()
|
||||||
@ -498,6 +501,8 @@ void Client::step(float dtime)
|
|||||||
*/
|
*/
|
||||||
LocalPlayer *player = m_env.getLocalPlayer();
|
LocalPlayer *player = m_env.getLocalPlayer();
|
||||||
|
|
||||||
|
m_sscsm_controller->eventOnStep(this, dtime);
|
||||||
|
|
||||||
// Step environment (also handles player controls)
|
// Step environment (also handles player controls)
|
||||||
m_env.step(dtime);
|
m_env.step(dtime);
|
||||||
m_sound->step(dtime);
|
m_sound->step(dtime);
|
||||||
|
@ -55,6 +55,8 @@ struct MeshMakeData;
|
|||||||
struct MinimapMapblock;
|
struct MinimapMapblock;
|
||||||
struct PlayerControl;
|
struct PlayerControl;
|
||||||
struct PointedThing;
|
struct PointedThing;
|
||||||
|
class ClientScripting;
|
||||||
|
class SSCSMController;
|
||||||
|
|
||||||
namespace con {
|
namespace con {
|
||||||
class IConnection;
|
class IConnection;
|
||||||
@ -98,8 +100,6 @@ private:
|
|||||||
std::map<u16, u32> m_packets;
|
std::map<u16, u32> m_packets;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClientScripting;
|
|
||||||
|
|
||||||
class Client : public con::PeerHandler, public InventoryManager, public IGameDef
|
class Client : public con::PeerHandler, public InventoryManager, public IGameDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -582,6 +582,9 @@ private:
|
|||||||
std::vector<ModSpec> m_mods;
|
std::vector<ModSpec> m_mods;
|
||||||
StringMap m_mod_vfs;
|
StringMap m_mod_vfs;
|
||||||
|
|
||||||
|
// SSCSM
|
||||||
|
std::unique_ptr<SSCSMController> m_sscsm_controller;
|
||||||
|
|
||||||
bool m_shutdown = false;
|
bool m_shutdown = false;
|
||||||
|
|
||||||
// CSM restrictions byteflag
|
// CSM restrictions byteflag
|
||||||
|
@ -15,6 +15,8 @@ set(common_SCRIPT_SRCS
|
|||||||
set(client_SCRIPT_SRCS
|
set(client_SCRIPT_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scripting_mainmenu.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/scripting_mainmenu.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scripting_client.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/scripting_client.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sscsm_controller.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sscsm_environment.cpp
|
||||||
${client_SCRIPT_COMMON_SRCS}
|
${client_SCRIPT_COMMON_SRCS}
|
||||||
${client_SCRIPT_CPP_API_SRCS}
|
${client_SCRIPT_CPP_API_SRCS}
|
||||||
${client_SCRIPT_LUA_API_SRCS}
|
${client_SCRIPT_LUA_API_SRCS}
|
||||||
|
65
src/script/sscsm_controller.cpp
Normal file
65
src/script/sscsm_controller.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#include "sscsm_controller.h"
|
||||||
|
#include "sscsm_environment.h"
|
||||||
|
#include "sscsm_requests.h"
|
||||||
|
#include "sscsm_events.h"
|
||||||
|
#include "sscsm_stupid_channel.h"
|
||||||
|
|
||||||
|
std::unique_ptr<SSCSMController> SSCSMController::create()
|
||||||
|
{
|
||||||
|
auto channel = std::make_shared<StupidChannel>();
|
||||||
|
auto thread = std::make_unique<SSCSMEnvironment>(channel);
|
||||||
|
thread->start();
|
||||||
|
|
||||||
|
// Wait for thread to finish initializing.
|
||||||
|
auto req0 = deserializeSSCSMRequest(channel->recvB());
|
||||||
|
FATAL_ERROR_IF(!dynamic_cast<SSCSMRequestPollNextEvent *>(req0.get()),
|
||||||
|
"First request must be pollEvent.");
|
||||||
|
|
||||||
|
return std::make_unique<SSCSMController>(std::move(thread), channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSCSMController::SSCSMController(std::unique_ptr<SSCSMEnvironment> thread,
|
||||||
|
std::shared_ptr<StupidChannel> channel) :
|
||||||
|
m_thread(std::move(thread)), m_channel(std::move(channel))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SSCSMController::~SSCSMController()
|
||||||
|
{
|
||||||
|
// send tear-down
|
||||||
|
m_channel->sendB(serializeSSCSMAnswer(SSCSMAnswerPollNextEvent{
|
||||||
|
std::make_unique<SSCSMEventTearDown>()
|
||||||
|
}));
|
||||||
|
// wait for death
|
||||||
|
m_thread->stop();
|
||||||
|
m_thread->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSSCSMAnswer SSCSMController::handleRequest(Client *client, ISSCSMRequest *req)
|
||||||
|
{
|
||||||
|
return req->exec(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSCSMController::runEvent(Client *client, std::unique_ptr<ISSCSMEvent> event)
|
||||||
|
{
|
||||||
|
auto answer = serializeSSCSMAnswer(SSCSMAnswerPollNextEvent{std::move(event)});
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
auto request = deserializeSSCSMRequest(m_channel->exchangeB(std::move(answer)));
|
||||||
|
|
||||||
|
if (dynamic_cast<SSCSMRequestPollNextEvent *>(request.get()) != nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
answer = handleRequest(client, request.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSCSMController::eventOnStep(Client *client, f32 dtime)
|
||||||
|
{
|
||||||
|
runEvent(client, std::make_unique<SSCSMEventOnStep>(dtime));
|
||||||
|
}
|
37
src/script/sscsm_controller.h
Normal file
37
src/script/sscsm_controller.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "irrlichttypes.h"
|
||||||
|
#include "sscsm_irequest.h"
|
||||||
|
#include "sscsm_ievent.h"
|
||||||
|
#include "util/basic_macros.h"
|
||||||
|
|
||||||
|
class SSCSMEnvironment;
|
||||||
|
class StupidChannel;
|
||||||
|
|
||||||
|
class SSCSMController
|
||||||
|
{
|
||||||
|
std::unique_ptr<SSCSMEnvironment> m_thread;
|
||||||
|
std::shared_ptr<StupidChannel> m_channel;
|
||||||
|
|
||||||
|
SerializedSSCSMAnswer handleRequest(Client *client, ISSCSMRequest *req);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<SSCSMController> create();
|
||||||
|
|
||||||
|
SSCSMController(std::unique_ptr<SSCSMEnvironment> thread,
|
||||||
|
std::shared_ptr<StupidChannel> channel);
|
||||||
|
|
||||||
|
~SSCSMController();
|
||||||
|
|
||||||
|
DISABLE_CLASS_COPY(SSCSMController);
|
||||||
|
|
||||||
|
// Handles requests until the next event is polled
|
||||||
|
void runEvent(Client *client, std::unique_ptr<ISSCSMEvent> event);
|
||||||
|
|
||||||
|
void eventOnStep(Client *client, f32 dtime);
|
||||||
|
};
|
47
src/script/sscsm_environment.cpp
Normal file
47
src/script/sscsm_environment.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#include "sscsm_environment.h"
|
||||||
|
#include "sscsm_requests.h"
|
||||||
|
#include "sscsm_events.h"
|
||||||
|
#include "sscsm_stupid_channel.h"
|
||||||
|
|
||||||
|
|
||||||
|
void *SSCSMEnvironment::run()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
auto next_event = cmdPollNextEvent();
|
||||||
|
|
||||||
|
if (dynamic_cast<SSCSMEventTearDown *>(next_event.get())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_event->exec(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSSCSMAnswer SSCSMEnvironment::exchange(SerializedSSCSMRequest req)
|
||||||
|
{
|
||||||
|
return m_channel->exchangeA(std::move(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ISSCSMEvent> SSCSMEnvironment::cmdPollNextEvent()
|
||||||
|
{
|
||||||
|
auto request = SSCSMRequestPollNextEvent{};
|
||||||
|
auto answer = deserializeSSCSMAnswer<SSCSMAnswerPollNextEvent>(
|
||||||
|
exchange(serializeSSCSMRequest(request))
|
||||||
|
);
|
||||||
|
return std::move(answer.next_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
MapNode SSCSMEnvironment::cmdGetNode(v3s16 pos)
|
||||||
|
{
|
||||||
|
auto request = SSCSMRequestGetNode{pos};
|
||||||
|
auto answer = deserializeSSCSMAnswer<SSCSMAnswerGetNode>(
|
||||||
|
exchange(serializeSSCSMRequest(request))
|
||||||
|
);
|
||||||
|
return answer.node;
|
||||||
|
}
|
32
src/script/sscsm_environment.h
Normal file
32
src/script/sscsm_environment.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "client/client.h"
|
||||||
|
#include "threading/thread.h"
|
||||||
|
#include "sscsm_controller.h"
|
||||||
|
#include "sscsm_irequest.h"
|
||||||
|
|
||||||
|
// The thread that runs SSCSM code.
|
||||||
|
// Meant to be replaced by a sandboxed process.
|
||||||
|
class SSCSMEnvironment : public Thread
|
||||||
|
{
|
||||||
|
std::shared_ptr<StupidChannel> m_channel;
|
||||||
|
|
||||||
|
void *run() override;
|
||||||
|
|
||||||
|
SerializedSSCSMAnswer exchange(SerializedSSCSMRequest req);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SSCSMEnvironment(std::shared_ptr<StupidChannel> channel) :
|
||||||
|
Thread("SSCSMEnvironment-thread"),
|
||||||
|
m_channel(std::move(channel))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ISSCSMEvent> cmdPollNextEvent();
|
||||||
|
MapNode cmdGetNode(v3s16 pos);
|
||||||
|
};
|
34
src/script/sscsm_events.h
Normal file
34
src/script/sscsm_events.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sscsm_ievent.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "irrlichttypes.h"
|
||||||
|
#include "irr_v3d.h"
|
||||||
|
#include "sscsm_environment.h"
|
||||||
|
#include "mapnode.h"
|
||||||
|
|
||||||
|
struct SSCSMEventTearDown : public ISSCSMEvent
|
||||||
|
{
|
||||||
|
void exec(SSCSMEnvironment *env) override
|
||||||
|
{
|
||||||
|
FATAL_ERROR("SSCSMEventTearDown needs to be handled by SSCSMEnvironment::run()");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SSCSMEventOnStep : public ISSCSMEvent
|
||||||
|
{
|
||||||
|
f32 dtime;
|
||||||
|
|
||||||
|
SSCSMEventOnStep(f32 dtime_) : dtime(dtime_) {}
|
||||||
|
|
||||||
|
void exec(SSCSMEnvironment *env) override
|
||||||
|
{
|
||||||
|
// example
|
||||||
|
env->cmdGetNode(v3s16(0, 0, 0));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
39
src/script/sscsm_ievent.h
Normal file
39
src/script/sscsm_ievent.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
class SSCSMEnvironment;
|
||||||
|
|
||||||
|
// Event triggered from the main env for the SSCSM env.
|
||||||
|
struct ISSCSMEvent
|
||||||
|
{
|
||||||
|
virtual ~ISSCSMEvent() = default;
|
||||||
|
|
||||||
|
// Note: No return value (difference to ISSCSMRequest). These are not callbacks
|
||||||
|
// that you can run at arbitrary locations, because the untrusted code could
|
||||||
|
// then clobber your local variables.
|
||||||
|
virtual void exec(SSCSMEnvironment *cntrl) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: actually serialize, and replace this with a string
|
||||||
|
using SerializedSSCSMEvent = std::unique_ptr<ISSCSMEvent>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline SerializedSSCSMEvent serializeSSCSMEvent(const T &event)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of_v<ISSCSMEvent, T>);
|
||||||
|
|
||||||
|
return std::make_unique<T>(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::unique_ptr<ISSCSMEvent> deserializeSSCSMEvent(SerializedSSCSMEvent event_serialized)
|
||||||
|
{
|
||||||
|
// The actual deserialization will have to use a type tag, and then choose
|
||||||
|
// the appropriate deserializer.
|
||||||
|
return event_serialized;
|
||||||
|
}
|
67
src/script/sscsm_irequest.h
Normal file
67
src/script/sscsm_irequest.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "exceptions.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
class SSCSMController;
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
struct ISSCSMAnswer
|
||||||
|
{
|
||||||
|
virtual ~ISSCSMAnswer() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: actually serialize, and replace this with a string
|
||||||
|
using SerializedSSCSMAnswer = std::unique_ptr<ISSCSMAnswer>;
|
||||||
|
|
||||||
|
// Request made by the sscsm env to the main env.
|
||||||
|
struct ISSCSMRequest
|
||||||
|
{
|
||||||
|
virtual ~ISSCSMRequest() = default;
|
||||||
|
|
||||||
|
virtual SerializedSSCSMAnswer exec(Client *client) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: actually serialize, and replace this with a string
|
||||||
|
using SerializedSSCSMRequest = std::unique_ptr<ISSCSMRequest>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline SerializedSSCSMRequest serializeSSCSMRequest(const T &request)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of_v<ISSCSMRequest, T>);
|
||||||
|
|
||||||
|
return std::make_unique<T>(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T deserializeSSCSMAnswer(SerializedSSCSMAnswer answer_serialized)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of_v<ISSCSMAnswer, T>);
|
||||||
|
|
||||||
|
// dynamic cast in place of actual deserialization
|
||||||
|
auto ptr = dynamic_cast<T *>(answer_serialized.get());
|
||||||
|
if (!ptr) {
|
||||||
|
throw SerializationError("deserializeSSCSMAnswer failed");
|
||||||
|
}
|
||||||
|
return std::move(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline SerializedSSCSMAnswer serializeSSCSMAnswer(T answer)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of_v<ISSCSMAnswer, T>);
|
||||||
|
|
||||||
|
return std::make_unique<T>(std::move(answer));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::unique_ptr<ISSCSMRequest> deserializeSSCSMRequest(SerializedSSCSMRequest request_serialized)
|
||||||
|
{
|
||||||
|
// The actual deserialization will have to use a type tag, and then choose
|
||||||
|
// the appropriate deserializer.
|
||||||
|
return request_serialized;
|
||||||
|
}
|
50
src/script/sscsm_requests.h
Normal file
50
src/script/sscsm_requests.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sscsm_irequest.h"
|
||||||
|
#include "sscsm_ievent.h"
|
||||||
|
#include "mapnode.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "client/client.h"
|
||||||
|
|
||||||
|
struct SSCSMAnswerPollNextEvent : public ISSCSMAnswer
|
||||||
|
{
|
||||||
|
std::unique_ptr<ISSCSMEvent> next_event;
|
||||||
|
|
||||||
|
SSCSMAnswerPollNextEvent(std::unique_ptr<ISSCSMEvent> next_event_) :
|
||||||
|
next_event(std::move(next_event_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SSCSMRequestPollNextEvent : public ISSCSMRequest
|
||||||
|
{
|
||||||
|
SerializedSSCSMAnswer exec(Client *client) override
|
||||||
|
{
|
||||||
|
FATAL_ERROR("SSCSMRequestPollNextEvent needs to be handled by SSCSMControler::runEvent()");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SSCSMAnswerGetNode : public ISSCSMAnswer
|
||||||
|
{
|
||||||
|
MapNode node;
|
||||||
|
|
||||||
|
SSCSMAnswerGetNode(MapNode node_) : node(node_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SSCSMRequestGetNode : public ISSCSMRequest
|
||||||
|
{
|
||||||
|
v3s16 pos;
|
||||||
|
|
||||||
|
SSCSMRequestGetNode(v3s16 pos_) : pos(pos_) {}
|
||||||
|
|
||||||
|
SerializedSSCSMAnswer exec(Client *client) override
|
||||||
|
{
|
||||||
|
MapNode node = client->getEnv().getMap().getNode(pos);
|
||||||
|
|
||||||
|
return serializeSSCSMAnswer(SSCSMAnswerGetNode{node});
|
||||||
|
}
|
||||||
|
};
|
84
src/script/sscsm_stupid_channel.h
Normal file
84
src/script/sscsm_stupid_channel.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Luanti authors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include "sscsm_irequest.h"
|
||||||
|
|
||||||
|
// FIXME: replace this with an ipc channel
|
||||||
|
class StupidChannel
|
||||||
|
{
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::condition_variable m_condvar;
|
||||||
|
SerializedSSCSMRequest m_request;
|
||||||
|
SerializedSSCSMAnswer m_answer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void sendA(SerializedSSCSMRequest request)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto lock = std::lock_guard(m_mutex);
|
||||||
|
|
||||||
|
m_request = std::move(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_condvar.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSSCSMAnswer recvA()
|
||||||
|
{
|
||||||
|
auto lock = std::unique_lock(m_mutex);
|
||||||
|
|
||||||
|
while (!m_answer) {
|
||||||
|
m_condvar.wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto answer = std::move(m_answer);
|
||||||
|
m_answer = nullptr;
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSSCSMAnswer exchangeA(SerializedSSCSMRequest request)
|
||||||
|
{
|
||||||
|
sendA(std::move(request));
|
||||||
|
|
||||||
|
return recvA();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendB(SerializedSSCSMAnswer answer)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto lock = std::lock_guard(m_mutex);
|
||||||
|
|
||||||
|
m_answer = std::move(answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_condvar.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSSCSMRequest recvB()
|
||||||
|
{
|
||||||
|
auto lock = std::unique_lock(m_mutex);
|
||||||
|
|
||||||
|
while (!m_request) {
|
||||||
|
m_condvar.wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto request = std::move(m_request);
|
||||||
|
m_request = nullptr;
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedSSCSMRequest exchangeB(SerializedSSCSMAnswer answer)
|
||||||
|
{
|
||||||
|
sendB(std::move(answer));
|
||||||
|
|
||||||
|
return recvB();
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user