summaryrefslogtreecommitdiffstats
path: root/src/dm/systems/Qt3DSDMSignalSystem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dm/systems/Qt3DSDMSignalSystem.cpp')
-rw-r--r--src/dm/systems/Qt3DSDMSignalSystem.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/dm/systems/Qt3DSDMSignalSystem.cpp b/src/dm/systems/Qt3DSDMSignalSystem.cpp
new file mode 100644
index 0000000..37d0200
--- /dev/null
+++ b/src/dm/systems/Qt3DSDMSignalSystem.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSDMPrefix.h"
+#include "Qt3DSDMSignalSystem.h"
+#include "EASTL/hash_map.h"
+
+using namespace qt3dsdm;
+
+namespace {
+
+struct SSignalListener;
+class ISignalSystemImpl
+{
+public:
+ virtual ~ISignalSystemImpl() {}
+ virtual void RemoveListener(SSignalListener &inListener) = 0;
+};
+
+struct SSignalSystemKey
+{
+ void *m_Sender;
+ const char *m_SignalName;
+ SSignalSystemKey(void *inSender, const char *inSigName, IStringTable &inStrTable)
+ : m_Sender(inSender)
+ , m_SignalName(inStrTable.GetNarrowStr(inSigName))
+ {
+ }
+ SSignalSystemKey(const SSignalSystemKey &inOther)
+ : m_Sender(inOther.m_Sender)
+ , m_SignalName(inOther.m_SignalName)
+ {
+ }
+
+ SSignalSystemKey &operator=(const SSignalSystemKey &inOther)
+ {
+ if (this != &inOther) {
+ m_Sender = inOther.m_Sender;
+ m_SignalName = inOther.m_SignalName;
+ }
+ return *this;
+ }
+
+ bool operator==(const SSignalSystemKey &inOther) const
+ {
+ return m_Sender == inOther.m_Sender && m_SignalName == inOther.m_SignalName;
+ }
+};
+
+struct SSignalListener : ISignalConnection
+{
+ shared_ptr<ISignalSystemImpl> m_SignalSystem;
+ TGenericSignalHandlerFunc m_Handler;
+ SSignalSystemKey m_Key;
+ SSignalListener(shared_ptr<ISignalSystemImpl> inSystem, TGenericSignalHandlerFunc inHandler,
+ SSignalSystemKey inKey)
+ : m_SignalSystem(inSystem)
+ , m_Handler(inHandler)
+ , m_Key(inKey)
+ {
+ }
+ ~SSignalListener() { m_SignalSystem->RemoveListener(*this); }
+ void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize)
+ {
+ m_Handler(inSender, inName, inData, inDataSize);
+ }
+};
+
+typedef eastl::vector<SSignalListener *> TSignalListenerPtrList;
+}
+
+namespace eastl {
+template <>
+struct hash<SSignalSystemKey>
+{
+ size_t operator()(const SSignalSystemKey &inKey) const
+ {
+ return hash<void *>()(inKey.m_Sender) ^ hash<const char *>()(inKey.m_SignalName);
+ }
+};
+}
+
+namespace {
+typedef eastl::hash_map<SSignalSystemKey, TSignalListenerPtrList> TSignalHandlerMap;
+
+struct SSignalSystemImpl : public ISignalSystemImpl
+{
+ TSignalHandlerMap m_SignalHandlers;
+ shared_ptr<IStringTable> m_StringTable;
+ SSignalSystemImpl(shared_ptr<IStringTable> inStrTable)
+ : m_StringTable(inStrTable)
+ {
+ }
+
+ TSignalListenerPtrList *FindListenerList(const SSignalSystemKey &inKey)
+ {
+ TSignalHandlerMap::iterator theIter = m_SignalHandlers.find(inKey);
+ if (theIter != m_SignalHandlers.end())
+ return &theIter->second;
+ return NULL;
+ }
+
+ void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize)
+ {
+ TSignalListenerPtrList *theSignals =
+ FindListenerList(SSignalSystemKey(inSender, inName, *m_StringTable));
+ if (theSignals) {
+ for (eastl_size_t idx = 0, end = theSignals->size(); idx < end; ++idx) {
+ (*theSignals)[idx]->Signal(inSender, inName, inData, inDataSize);
+ }
+ }
+ }
+
+ void RemoveListener(SSignalListener &inListener) override
+ {
+ TSignalListenerPtrList *theSignals = FindListenerList(inListener.m_Key);
+ if (theSignals) {
+ // If we could allow unordered access then this could potentially be a lot faster.
+ TSignalListenerPtrList::iterator theFind =
+ eastl::find(theSignals->begin(), theSignals->end(), &inListener);
+ if (theFind != theSignals->end())
+ theSignals->erase(theFind);
+ }
+ }
+};
+
+struct SSignalSystem : public ISignalSystem
+{
+ shared_ptr<SSignalSystemImpl> m_System;
+ SSignalSystem(shared_ptr<IStringTable> inStrTable)
+ {
+ m_System = std::make_shared<SSignalSystemImpl>(inStrTable);
+ }
+
+ shared_ptr<ISignalConnection> AddListener(void *inSender, const char *inName,
+ TGenericSignalHandlerFunc inFunc) override
+ {
+ SSignalSystemKey theKey(inSender, inName, *m_System->m_StringTable);
+ TSignalHandlerMap::iterator theIter =
+ m_System->m_SignalHandlers.insert(eastl::make_pair(theKey, TSignalListenerPtrList()))
+ .first;
+ TSignalListenerPtrList &theList(theIter->second);
+ shared_ptr<SSignalListener> theSender =
+ std::make_shared<SSignalListener>(m_System, inFunc, theKey);
+ theList.push_back(theSender.get());
+ return theSender;
+ }
+
+ void Signal(void *inSender, const char *inName, const char *inData, size_t inDataSize) override
+ {
+ m_System->Signal(inSender, inName, inData, inDataSize);
+ }
+};
+}
+
+shared_ptr<ISignalSystem> ISignalSystem::CreateSignalSystem(shared_ptr<IStringTable> inStrTable)
+{
+ return std::make_shared<SSignalSystem>(inStrTable);
+}