mirror of https://github.com/zeldaret/botw.git
ksys: Implement several more MessageDispatcher functions
This commit is contained in:
parent
76b9041c78
commit
dfef8dfff7
|
@ -92641,10 +92641,10 @@
|
||||||
0x00000071011f4db4,GlobalMessage::dtorDelete,36,_ZN4ksys17MessageDispatcherD0Ev
|
0x00000071011f4db4,GlobalMessage::dtorDelete,36,_ZN4ksys17MessageDispatcherD0Ev
|
||||||
0x00000071011f4dd8,GlobalMessage::init,580,_ZN4ksys17MessageDispatcher4initERKNS0_7InitArgEPN4sead4HeapE
|
0x00000071011f4dd8,GlobalMessage::init,580,_ZN4ksys17MessageDispatcher4initERKNS0_7InitArgEPN4sead4HeapE
|
||||||
0x00000071011f501c,GlobalMessage::currentTlsSlotIsSame,56,_ZNK4ksys17MessageDispatcher27isProcessingOnCurrentThreadEv
|
0x00000071011f501c,GlobalMessage::currentTlsSlotIsSame,56,_ZNK4ksys17MessageDispatcher27isProcessingOnCurrentThreadEv
|
||||||
0x00000071011f5054,GlobalMessage::x,376,
|
0x00000071011f5054,GlobalMessage::x,376,_ZN4ksys17MessageDispatcher19registerTransceiverERNS_17MessageReceiverExE
|
||||||
0x00000071011f51cc,GlobalMessage::x_0,344,
|
0x00000071011f51cc,GlobalMessage::x_0,344,_ZN4ksys17MessageDispatcher21deregisterTransceiverERNS_17MessageReceiverExE
|
||||||
0x00000071011f5324,GlobalMessage::x_1,124,
|
0x00000071011f5324,GlobalMessage::x_1,124,_ZN4ksys17MessageDispatcher11sendMessageERKNS_16MesTransceiverIdES3_RKNS_11MessageTypeEPvb
|
||||||
0x00000071011f53a0,GlobalMessage::x_5,236,
|
0x00000071011f53a0,GlobalMessage::x_5,236,_ZN4ksys17MessageDispatcher29sendMessageOnProcessingThreadERKNS_16MesTransceiverIdES3_RKNS_11MessageTypeEPvb?
|
||||||
0x00000071011f548c,GlobalMessage::x_2,208,
|
0x00000071011f548c,GlobalMessage::x_2,208,
|
||||||
0x00000071011f555c,GlobalMessage::x_3,268,
|
0x00000071011f555c,GlobalMessage::x_3,268,
|
||||||
0x00000071011f5668,GlobalMessage::x_4,248,
|
0x00000071011f5668,GlobalMessage::x_4,248,
|
||||||
|
|
Can't render this file because it is too large.
|
2
lib/sead
2
lib/sead
|
@ -1 +1 @@
|
||||||
Subproject commit 1737b022c7b70c04cc2471ff58d00ead1b6b6a93
|
Subproject commit ac3d8764bba7dedeea62ce0d6841b0f801111321
|
|
@ -88,19 +88,7 @@ public:
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid() const { return checkTransceiver(mDestination); }
|
bool isValid() const { return mDestination.isRegistered(); }
|
||||||
|
|
||||||
static bool checkTransceiver(const MesTransceiverId& id) {
|
|
||||||
if (!id.next)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
MesTransceiverId* next = *id.next;
|
|
||||||
if (!next)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto& fields = [](const MesTransceiverId& i) { return std::tie(i.queue_id, i.id); };
|
|
||||||
return fields(id) == fields(*next);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MesTransceiverId mSource{};
|
MesTransceiverId mSource{};
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
#include "KingSystem/Utils/Thread/MessageDispatcher.h"
|
#include "KingSystem/Utils/Thread/MessageDispatcher.h"
|
||||||
#include <heap/seadHeapMgr.h>
|
#include <heap/seadHeapMgr.h>
|
||||||
#include <prim/seadMemUtil.h>
|
#include <prim/seadMemUtil.h>
|
||||||
|
#include <prim/seadScopedLock.h>
|
||||||
#include <thread/seadThread.h>
|
#include <thread/seadThread.h>
|
||||||
|
#include "KingSystem/Utils/Debug.h"
|
||||||
#include "KingSystem/Utils/HeapUtil.h"
|
#include "KingSystem/Utils/HeapUtil.h"
|
||||||
#include "KingSystem/Utils/SafeDelete.h"
|
#include "KingSystem/Utils/SafeDelete.h"
|
||||||
#include "KingSystem/Utils/Thread/Message.h"
|
#include "KingSystem/Utils/Thread/Message.h"
|
||||||
|
#include "KingSystem/Utils/Thread/MessageReceiverEx.h"
|
||||||
|
|
||||||
namespace ksys {
|
namespace ksys {
|
||||||
|
|
||||||
|
@ -23,10 +26,10 @@ Message* MessageDispatcher::Queue::findUnusedEntry() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MessageDispatcher::Queue::addMessage(const Message& message) {
|
bool MessageDispatcher::Queue::addMessage(const Message& message) {
|
||||||
if (!Message::checkTransceiver(message.getSource()))
|
if (!message.getSource().isRegistered())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!Message::checkTransceiver(message.getDestination()))
|
if (!message.getDestination().isRegistered())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto* entry = findUnusedEntry();
|
auto* entry = findUnusedEntry();
|
||||||
|
@ -66,7 +69,6 @@ void MessageDispatcher::DoubleBufferedQueue::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageDispatcher::DoubleBufferedQueue::processQueue(MessageProcessor& processor) {
|
void MessageDispatcher::DoubleBufferedQueue::processQueue(MessageProcessor& processor) {
|
||||||
mActiveIdx ^= 1;
|
|
||||||
mBuffer[mActiveIdx].processQueue(processor);
|
mBuffer[mActiveIdx].processQueue(processor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +96,7 @@ void MessageDispatcher::MainQueue::clear() {
|
||||||
void MessageDispatcher::MainQueue::processQueue(MessageProcessor& processor) {
|
void MessageDispatcher::MainQueue::processQueue(MessageProcessor& processor) {
|
||||||
for (u32 i = 0; mHasMessageToProcess && i < 1000; ++i) {
|
for (u32 i = 0; mHasMessageToProcess && i < 1000; ++i) {
|
||||||
mHasMessageToProcess = false;
|
mHasMessageToProcess = false;
|
||||||
|
mQueue.swapBuffer();
|
||||||
mQueue.processQueue(processor);
|
mQueue.processQueue(processor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +108,7 @@ MessageDispatcher::Queues::TransceiverIdBuffer::TransceiverIdBuffer() {
|
||||||
|
|
||||||
MessageDispatcher::Queues::TransceiverIdBuffer::~TransceiverIdBuffer() {
|
MessageDispatcher::Queues::TransceiverIdBuffer::~TransceiverIdBuffer() {
|
||||||
for (auto it = mBuffer.begin(); it != mBuffer.end(); ++it) {
|
for (auto it = mBuffer.begin(); it != mBuffer.end(); ++it) {
|
||||||
if (auto* id = *it; id && Message::checkTransceiver(*id))
|
if (auto* id = *it; id && id->isRegistered())
|
||||||
id->reset();
|
id->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,4 +156,113 @@ bool MessageDispatcher::isProcessingOnCurrentThread() const {
|
||||||
return mProcessingThread == sead::ThreadMgr::instance()->getCurrentThread();
|
return mProcessingThread == sead::ThreadMgr::instance()->getCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageDispatcher::registerTransceiver(MessageReceiverEx& receiver) {
|
||||||
|
const auto lock = sead::makeScopedLock(mCritSection);
|
||||||
|
Queues& queues = *mQueues;
|
||||||
|
receiver.setQueueId(queues.getId());
|
||||||
|
MesTransceiverId** ref = nullptr;
|
||||||
|
{
|
||||||
|
const auto queue_lock = sead::makeScopedLock(queues.getCritSection());
|
||||||
|
MesTransceiverId* id = receiver.getId();
|
||||||
|
|
||||||
|
if (!id->isRegistered()) {
|
||||||
|
const auto& pointers = queues.getIdPointers();
|
||||||
|
for (auto it = pointers.begin(); it != pointers.end(); ++it) {
|
||||||
|
if (*it == nullptr) {
|
||||||
|
ref = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref) {
|
||||||
|
*ref = id;
|
||||||
|
id->self_ref = ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ref) {
|
||||||
|
sead::FormatFixedSafeString<128> msg{"↓↓↓\nエントリー数 : %d\n↑↑↑\n", mNumEntries.load()};
|
||||||
|
util::PrintDebug(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mNumEntries.increment();
|
||||||
|
if (!mBools.isEmpty())
|
||||||
|
receiver.setFlagPointer(mBools.popFront());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageDispatcher::deregisterTransceiver(MessageReceiverEx& receiver) {
|
||||||
|
if (receiver.checkFlag() && receiver.checkCounter())
|
||||||
|
mUpdateEndEvent.wait();
|
||||||
|
|
||||||
|
const auto lock = sead::makeScopedLock(mCritSection);
|
||||||
|
if (!receiver.getId()->isRegistered())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto* ptr = receiver.getFlagPointer();
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mBools.emplaceBack(ptr);
|
||||||
|
receiver.clearFlagPointer();
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto queue_lock = sead::makeScopedLock(mQueues->getCritSection());
|
||||||
|
auto& id = *receiver.getId();
|
||||||
|
if (id.isRegistered()) {
|
||||||
|
auto* self = id.self_ref;
|
||||||
|
id.self_ref = nullptr;
|
||||||
|
*self = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mNumEntries.decrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageDispatcher::sendMessage(const MesTransceiverId& src, const MesTransceiverId& dest,
|
||||||
|
const MessageType& type, void* user_data, bool ack) {
|
||||||
|
auto* queues = mQueues;
|
||||||
|
const auto message = Message{src, dest, type, user_data, {}, ack};
|
||||||
|
const auto lock = sead::makeScopedLock(queues->getCritSection());
|
||||||
|
return queues->getQueue().addMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NON_MATCHING: branching: deduplicated Message destructor call
|
||||||
|
bool MessageDispatcher::sendMessageOnProcessingThread(const MesTransceiverId& src,
|
||||||
|
const MesTransceiverId& dest,
|
||||||
|
const MessageType& type, void* user_data,
|
||||||
|
bool ack) {
|
||||||
|
if (!isProcessingOnCurrentThread())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto* queues = mQueues;
|
||||||
|
const auto message = Message{src, dest, type, user_data, {}, ack};
|
||||||
|
if (!queues->isProcessing())
|
||||||
|
return false;
|
||||||
|
return queues->getMainQueue().addMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageDispatcher::Queues::process() {
|
||||||
|
{
|
||||||
|
const auto lock = sead::makeScopedLock(mCritSection);
|
||||||
|
mQueue.swapBuffer();
|
||||||
|
}
|
||||||
|
mIsProcessing = true;
|
||||||
|
mQueue.processQueue(mProcessor);
|
||||||
|
mMainQueue.processQueue(mProcessor);
|
||||||
|
mIsProcessing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageDispatcher::update() {
|
||||||
|
mUpdateEndEvent.resetSignal();
|
||||||
|
mProcessingThread = sead::ThreadMgr::instance()->getCurrentThread();
|
||||||
|
|
||||||
|
mQueues->process();
|
||||||
|
|
||||||
|
sead::MemUtil::fillZero(mBoolBuffer.getBufferPtr(), mBoolBuffer.getByteSize());
|
||||||
|
mProcessingThread = nullptr;
|
||||||
|
mUpdateEndEvent.setSignal();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ksys
|
} // namespace ksys
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <heap/seadDisposer.h>
|
#include <heap/seadDisposer.h>
|
||||||
#include <prim/seadRuntimeTypeInfo.h>
|
#include <prim/seadRuntimeTypeInfo.h>
|
||||||
#include <prim/seadTypedBitFlag.h>
|
#include <prim/seadTypedBitFlag.h>
|
||||||
|
#include <thread/seadAtomic.h>
|
||||||
#include <thread/seadCriticalSection.h>
|
#include <thread/seadCriticalSection.h>
|
||||||
#include "KingSystem/Utils/Thread/Event.h"
|
#include "KingSystem/Utils/Thread/Event.h"
|
||||||
#include "KingSystem/Utils/Thread/MessageDispatcherBase.h"
|
#include "KingSystem/Utils/Thread/MessageDispatcherBase.h"
|
||||||
|
@ -19,6 +20,7 @@ namespace ksys {
|
||||||
|
|
||||||
class Message;
|
class Message;
|
||||||
class MessageProcessor;
|
class MessageProcessor;
|
||||||
|
struct MesTransceiverId;
|
||||||
|
|
||||||
class MessageDispatcher : public MessageDispatcherBase {
|
class MessageDispatcher : public MessageDispatcherBase {
|
||||||
SEAD_SINGLETON_DISPOSER(MessageDispatcher)
|
SEAD_SINGLETON_DISPOSER(MessageDispatcher)
|
||||||
|
@ -71,13 +73,14 @@ private:
|
||||||
bool addMessage(const Message& message);
|
bool addMessage(const Message& message);
|
||||||
void clear();
|
void clear();
|
||||||
void processQueue(MessageProcessor& processor);
|
void processQueue(MessageProcessor& processor);
|
||||||
|
void swapBuffer() { mActiveIdx ^= 1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 mActiveIdx = 1;
|
u32 mActiveIdx = 1;
|
||||||
Queue mBuffer[2];
|
Queue mBuffer[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
class MainQueue {
|
class MainQueue final {
|
||||||
public:
|
public:
|
||||||
MainQueue();
|
MainQueue();
|
||||||
virtual ~MainQueue();
|
virtual ~MainQueue();
|
||||||
|
@ -94,6 +97,13 @@ private:
|
||||||
public:
|
public:
|
||||||
explicit Queues(MessageProcessor::Logger* logger);
|
explicit Queues(MessageProcessor::Logger* logger);
|
||||||
~Queues();
|
~Queues();
|
||||||
|
const u32& getId() const { return mId; }
|
||||||
|
sead::CriticalSection& getCritSection() { return mCritSection; }
|
||||||
|
const auto& getIdPointers() const { return mTransceiverIdPtrs.mBuffer; }
|
||||||
|
DoubleBufferedQueue& getQueue() { return mQueue; }
|
||||||
|
MainQueue& getMainQueue() { return mMainQueue; }
|
||||||
|
bool isProcessing() const { return mIsProcessing; }
|
||||||
|
void process();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct DummyLogger : public MessageProcessor::Logger {
|
struct DummyLogger : public MessageProcessor::Logger {
|
||||||
|
@ -111,7 +121,7 @@ private:
|
||||||
sead::CriticalSection mCritSection;
|
sead::CriticalSection mCritSection;
|
||||||
u32 mId = 0xffffffff;
|
u32 mId = 0xffffffff;
|
||||||
DummyLogger mDummyLogger;
|
DummyLogger mDummyLogger;
|
||||||
TransceiverIdBuffer mTransceiverIds;
|
TransceiverIdBuffer mTransceiverIdPtrs;
|
||||||
DoubleBufferedQueue mQueue;
|
DoubleBufferedQueue mQueue;
|
||||||
MainQueue mMainQueue;
|
MainQueue mMainQueue;
|
||||||
MessageProcessor mProcessor;
|
MessageProcessor mProcessor;
|
||||||
|
@ -131,11 +141,11 @@ private:
|
||||||
Logger mLogger{};
|
Logger mLogger{};
|
||||||
Queues* mQueues{};
|
Queues* mQueues{};
|
||||||
sead::TypedBitFlag<Flag> mFlags;
|
sead::TypedBitFlag<Flag> mFlags;
|
||||||
sead::Buffer<bool> mBoolBuffer;
|
sead::Buffer<u8> mBoolBuffer;
|
||||||
sead::ObjList<bool*> mBools;
|
sead::ObjList<u8*> mBools;
|
||||||
sead::CriticalSection mCritSection;
|
sead::CriticalSection mCritSection;
|
||||||
util::Event mUpdateEndEvent;
|
util::Event mUpdateEndEvent;
|
||||||
int mNumEntries = 0;
|
sead::Atomic<int> mNumEntries = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ksys
|
} // namespace ksys
|
||||||
|
|
|
@ -19,17 +19,17 @@ bool MessageProcessor::process(Message* message) {
|
||||||
bool dest_valid = false;
|
bool dest_valid = false;
|
||||||
|
|
||||||
const auto& dest = message->getDestination();
|
const auto& dest = message->getDestination();
|
||||||
if (Message::checkTransceiver(dest)) {
|
if (dest.isRegistered()) {
|
||||||
success = dest.receiver->receive(*message) & 1;
|
success = dest.receiver->receive(*message) & 1;
|
||||||
mLogger->log(*message, success);
|
mLogger->log(*message, success);
|
||||||
dest_valid = true;
|
dest_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& src = message->getSource();
|
const auto& src = message->getSource();
|
||||||
if (!message->hasDelayer() || Message::checkTransceiver(src)) {
|
if (!message->hasDelayer() || src.isRegistered()) {
|
||||||
if (message->shouldAck()) {
|
if (message->shouldAck()) {
|
||||||
const auto& source = message->getSource();
|
const auto& source = message->getSource();
|
||||||
if (Message::checkTransceiver(source)) {
|
if (source.isRegistered()) {
|
||||||
auto* receiver = source.receiver;
|
auto* receiver = source.receiver;
|
||||||
const MessageAck ack{dest_valid, success, message->getDestination(),
|
const MessageAck ack{dest_valid, success, message->getDestination(),
|
||||||
message->getType(), message->getUserData()};
|
message->getType(), message->getUserData()};
|
||||||
|
|
|
@ -17,6 +17,7 @@ public:
|
||||||
bool checkCounter() const;
|
bool checkCounter() const;
|
||||||
void setFlag(bool update_counter);
|
void setFlag(bool update_counter);
|
||||||
|
|
||||||
|
u8* getFlagPointer() const { return mFlag; }
|
||||||
void setFlagPointer(u8* ptr);
|
void setFlagPointer(u8* ptr);
|
||||||
void clearFlagPointer();
|
void clearFlagPointer();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <basis/seadTypes.h>
|
#include <basis/seadTypes.h>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include "KingSystem/Utils/Types.h"
|
#include "KingSystem/Utils/Types.h"
|
||||||
|
|
||||||
|
@ -9,30 +10,41 @@ namespace ksys {
|
||||||
class MessageReceiver;
|
class MessageReceiver;
|
||||||
|
|
||||||
struct MesTransceiverId {
|
struct MesTransceiverId {
|
||||||
MesTransceiverId() : receiver(), next() { reset(); }
|
MesTransceiverId() : receiver(), self_ref() { reset(); }
|
||||||
MesTransceiverId(const MesTransceiverId& other) { *this = other; }
|
MesTransceiverId(const MesTransceiverId& other) { *this = other; }
|
||||||
MesTransceiverId(u32& id, MessageReceiver* receiver) : id(++id), receiver(receiver), next() {}
|
MesTransceiverId(u32& id, MessageReceiver* receiver)
|
||||||
|
: id(++id), receiver(receiver), self_ref() {}
|
||||||
~MesTransceiverId() { reset(); }
|
~MesTransceiverId() { reset(); }
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
queue_id = 0xffffffff;
|
queue_id = 0xffffffff;
|
||||||
id = 0xffffffff;
|
id = 0xffffffff;
|
||||||
receiver = nullptr;
|
receiver = nullptr;
|
||||||
next = nullptr;
|
self_ref = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MesTransceiverId& operator=(const MesTransceiverId& other) {
|
MesTransceiverId& operator=(const MesTransceiverId& other) {
|
||||||
queue_id = other.queue_id;
|
queue_id = other.queue_id;
|
||||||
id = other.id;
|
id = other.id;
|
||||||
receiver = other.receiver;
|
receiver = other.receiver;
|
||||||
next = other.next;
|
self_ref = other.self_ref;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isRegistered() const {
|
||||||
|
if (!self_ref || !*self_ref)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto fields = [](const MesTransceiverId& i) { return std::tie(i.queue_id, i.id); };
|
||||||
|
return fields(*this) == fields(**self_ref);
|
||||||
|
}
|
||||||
|
|
||||||
u32 queue_id = 0xffffffff;
|
u32 queue_id = 0xffffffff;
|
||||||
u32 id = 0xffffffff;
|
u32 id = 0xffffffff;
|
||||||
MessageReceiver* receiver;
|
MessageReceiver* receiver;
|
||||||
MesTransceiverId** next;
|
/// If registered, this points to a pointer that points to this object.
|
||||||
|
/// Otherwise, this value is nullptr.
|
||||||
|
MesTransceiverId** self_ref;
|
||||||
};
|
};
|
||||||
KSYS_CHECK_SIZE_NX150(MesTransceiverId, 0x18);
|
KSYS_CHECK_SIZE_NX150(MesTransceiverId, 0x18);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue