From 3182eff1ad68ec9fc96512a44acd4b6f3e57bcd1 Mon Sep 17 00:00:00 2001 From: Calcitem Date: Sat, 7 Dec 2019 16:09:24 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E6=96=B0=E5=A2=9E=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E7=94=A8=E4=BA=8E=E6=9C=AC=E5=9C=B0=E5=AF=B9?= =?UTF-8?q?=E6=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用共享内存实现,效率比 socket 高。 打开 TEST_MODE 宏才能生效。 --- include/config.h | 2 + millgame.pro | 3 + millgame.vcxproj | 6 +- millgame.vcxproj.filters | 9 +++ src/base/aithread.h | 1 + src/test/test.cpp | 121 +++++++++++++++++++++++++++++++++++ src/test/test.h | 61 ++++++++++++++++++ src/ui/qt/gamecontroller.cpp | 26 +++++++- src/ui/qt/gamecontroller.h | 13 ++++ 9 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 src/test/test.cpp create mode 100644 src/test/test.h diff --git a/include/config.h b/include/config.h index cd567f3b..1dcd959b 100644 --- a/include/config.h +++ b/include/config.h @@ -30,6 +30,8 @@ //#define TRAINING_MODE +//#define TEST_MODE + //#define DEBUG_MODE //#define DEBUG_MODE_A diff --git a/millgame.pro b/millgame.pro index d3e9e3df..603f16ac 100644 --- a/millgame.pro +++ b/millgame.pro @@ -19,6 +19,7 @@ INCLUDEPATH += include INCLUDEPATH += src/base INCLUDEPATH += src/ai INCLUDEPATH += src/game +INCLUDEPATH += src/test INCLUDEPATH += src/ui/qt SOURCES += \ @@ -39,6 +40,7 @@ SOURCES += \ src/main.cpp \ src/base/aithread.cpp \ src/ai/search.cpp \ + src/test/test.cpp \ src/ui/qt/gamewindow.cpp \ src/ui/qt/pieceitem.cpp \ src/ui/qt/server.cpp \ @@ -75,6 +77,7 @@ HEADERS += \ src/game/position.h \ src/game/rule.h \ src/game/types.h \ + src/test/test.h \ src/ui/qt/client.h \ src/ui/qt/gamecontroller.h \ src/ui/qt/gamescene.h \ diff --git a/millgame.vcxproj b/millgame.vcxproj index 340cef93..4b62f24d 100644 --- a/millgame.vcxproj +++ b/millgame.vcxproj @@ -106,10 +106,10 @@ true - $(ProjectDir)\src\base;$(ProjectDir)\include;$(ProjectDir)\src\ai;$(ProjectDir)\src\game;$(ProjectDir)\src\ui\qt;$(IncludePath) + $(ProjectDir)\src\base;$(ProjectDir)\include;$(ProjectDir)\src\ai;$(ProjectDir)\src\game;$(ProjectDir)\src\ui\qt;$(ProjectDir)\src\test;$(IncludePath) - $(ProjectDir)\src\ui\qt;$(ProjectDir)\src\game;$(ProjectDir)\src\ai;$(ProjectDir)\src\base;$(ProjectDir)\include;$(IncludePath) + $(ProjectDir)\src\ui\qt;$(ProjectDir)\src\game;$(ProjectDir)\src\ai;$(ProjectDir)\src\base;$(ProjectDir)\include;$(ProjectDir)\src\test;$(IncludePath) @@ -466,6 +466,7 @@ + @@ -717,6 +718,7 @@ + diff --git a/millgame.vcxproj.filters b/millgame.vcxproj.filters index 8e582b55..d196e784 100644 --- a/millgame.vcxproj.filters +++ b/millgame.vcxproj.filters @@ -52,6 +52,9 @@ {c5349658-6cbb-4076-8529-29de7092f9d8} + + {944f132b-1dc6-4222-a345-79e3d2c821e7} + @@ -294,6 +297,9 @@ base + + test + @@ -374,6 +380,9 @@ base + + test + diff --git a/src/base/aithread.h b/src/base/aithread.h index 9f477233..834d6709 100644 --- a/src/base/aithread.h +++ b/src/base/aithread.h @@ -28,6 +28,7 @@ #include "search.h" #include "server.h" #include "client.h" +#include "test.h" class AiThread : public QThread { diff --git a/src/test/test.cpp b/src/test/test.cpp new file mode 100644 index 00000000..76bf342d --- /dev/null +++ b/src/test/test.cpp @@ -0,0 +1,121 @@ +/* + Sanmill, a mill game playing engine derived from NineChess 1.5 + Copyright (C) 2015-2018 liuweilhy (NineChess author) + Copyright (C) 2019 Calcitem + + Sanmill is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Sanmill is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "config.h" + +#ifdef TEST_MODE + +#include +#include +#include +#include +#include +#include + +#include "test.h" + +Test::Test() +{ + sharedMemory.setKey("MillGameSharedMemory"); + + if (sharedMemory.attach()) { + loggerDebug("Attached shared memory segment.\n"); + } else { + if (sharedMemory.create(SHARED_MEMORY_SIZE)) { + loggerDebug("Created shared memory segment.\n"); + } else { + loggerDebug("Unable to create shared memory segment.\n"); + } + } + + to = (char *)sharedMemory.data(); + + uuid = createUuidString(); + uuidSize = uuid.size(); + + assert(uuidSize == 38); +} + +Test::~Test() +{ + detach(); +} + +void Test::writeToMemory(const QString &cmdline) +{ + if (cmdline == readStr) { + return; + } + + char from[128] = { 0 }; + strcpy(from, cmdline.toStdString().c_str()); + + while (true) { + sharedMemory.lock(); + + if (to[0] != 0) { + sharedMemory.unlock(); + QThread::msleep(100); + continue; + } + + memset(to, 0, SHARED_MEMORY_SIZE); + memcpy(to, uuid.toStdString().c_str(), uuidSize); + memcpy(to + uuidSize, from, strlen(from)); + sharedMemory.unlock(); + + break; + } +} + +void Test::readFromMemory() +{ + sharedMemory.lock(); + QString str = to; + sharedMemory.unlock(); + + if (str.size() == 0) { + return; + } + + if (!(str.mid(0, uuidSize) == uuid)) { + str = str.mid(uuidSize); + if (str.size()) { + sharedMemory.lock(); + memset(to, 0, SHARED_MEMORY_SIZE); + sharedMemory.unlock(); + readStr = str; + emit command(str); + } + } +} + +void Test::detach() +{ + if (sharedMemory.isAttached()) { + sharedMemory.detach(); + } +} + +QString Test::createUuidString() +{ + return QUuid::createUuid().toString(); +} + +#endif // TEST_MODE diff --git a/src/test/test.h b/src/test/test.h new file mode 100644 index 00000000..42275d6f --- /dev/null +++ b/src/test/test.h @@ -0,0 +1,61 @@ +/* + Sanmill, a mill game playing engine derived from NineChess 1.5 + Copyright (C) 2015-2018 liuweilhy (NineChess author) + Copyright (C) 2019 Calcitem + + Sanmill is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Sanmill is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef TEST_H +#define TEST_H + +#include "config.h" + +#ifdef TEST_MODE + +#include +#include +#include +#include + +class Test : public QObject +{ + Q_OBJECT + +public: + Test(); + ~Test(); + +signals: + void command(const QString &cmd, bool update = true); + +public slots: + void writeToMemory(const QString &str); + void readFromMemory(); + +private: + void detach(); + QString createUuidString(); + +private: + const int SHARED_MEMORY_SIZE = 4096; + QSharedMemory sharedMemory; + QString uuid; + int uuidSize; + char *to { nullptr }; + QString readStr; +}; + +#endif // TEST_MODE +#endif // TEST_H diff --git a/src/ui/qt/gamecontroller.cpp b/src/ui/qt/gamecontroller.cpp index 1b698fca..fab6b077 100644 --- a/src/ui/qt/gamecontroller.cpp +++ b/src/ui/qt/gamecontroller.cpp @@ -76,12 +76,25 @@ GameController::GameController( gameReset(); +#ifdef TEST_MODE + gameTest = new Test(); + + readMemoryTimer = new QTimer(this); + connect(readMemoryTimer, SIGNAL(timeout()), this, SLOT(onTimeOut())); + readMemoryTimer->start(100); +#endif // TEST_MODE + // 关联AI和控制器的着法命令行 connect(aiThread[BLACK], SIGNAL(command(const QString &, bool)), this, SLOT(command(const QString &, bool))); connect(aiThread[WHITE], SIGNAL(command(const QString &, bool)), this, SLOT(command(const QString &, bool))); +#ifdef TEST_MODE + connect(this->gameTest, SIGNAL(command(const QString &, bool)), + this, SLOT(command(const QString &, bool))); +#endif + #ifndef TRAINING_MODE // 关联AI和网络类的着法命令行 connect(aiThread[BLACK]->getClient(), SIGNAL(command(const QString &, bool)), @@ -110,6 +123,13 @@ GameController::~GameController() #endif /* ENDGAME_LEARNING */ } +#ifdef TEST_MODE +void GameController::onTimeOut() +{ + gameTest->readFromMemory(); +} +#endif // TEST_MODE + const map GameController::getActions() { // 主窗口更新菜单栏 @@ -926,12 +946,16 @@ bool GameController::command(const QString &cmd, bool update /* = true */) #endif } +#ifdef TEST_MODE + gameTest->writeToMemory(cmd); +#endif // TEST_MODE + #ifndef TRAINING_MODE // 网络: 将着法放到服务器的发送列表中 if (isAiPlayer[BLACK]) { aiThread[BLACK]->getServer()->setAction(cmd); } else if (isAiPlayer[WHITE]) { - aiThread[BLACK]->getServer()->setAction(cmd); // 注意: 同样是AI1 + aiThread[BLACK]->getServer()->setAction(cmd); // 注意: 同样是 aiThread[BLACK] } #endif // TRAINING_MODE diff --git a/src/ui/qt/gamecontroller.h b/src/ui/qt/gamecontroller.h index a0be036c..7e105e5a 100644 --- a/src/ui/qt/gamecontroller.h +++ b/src/ui/qt/gamecontroller.h @@ -274,6 +274,11 @@ public slots: // 显示网络配置窗口 void showNetworkWindow(); +#ifdef TEST_MODE + // 定时器超时 + void onTimeOut(); +#endif // TEST_MODE + protected: //bool eventFilter(QObject * watched, QEvent * event); // 定时器 @@ -286,6 +291,11 @@ private: // 棋对象的数据模型(临时) Game tempGame; +#ifdef TEST_MODE + // 测试 + Test *gameTest; +#endif // TEST_MODE + private: // 2个AI的线程 AiThread *aiThread[COLOR_COUNT]; @@ -365,6 +375,9 @@ private: // 棋谱字符串列表模型 QStringListModel manualListModel; + + // 读取共享内存的定时器 + QTimer *readMemoryTimer; }; #endif // GAMECONTROLLER_H