Benjamin Kraft 2 years ago
parent b687946251
commit 17acf0a45a
  1. 11
      CMakeLists.txt
  2. 6
      main.cpp
  3. 16
      src/Audio.cpp
  4. 14
      src/Audio.h
  5. 21
      src/Event.h
  6. 30
      src/FileManager.cpp
  7. 25
      src/FileManager.h
  8. 17
      src/Listener.h
  9. 22
      src/Player.cpp
  10. 13
      src/Player.h
  11. 74
      src/Queue.h
  12. 43
      src/main.cpp

@ -3,4 +3,13 @@ project(EventQueue)
set(CMAKE_CXX_STANDARD 23)
add_executable(EventQueue main.cpp)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets)
file(GLOB_RECURSE SRC_FILES src/**.cpp)
file(GLOB_RECURSE HEADER_FILES src/**.h)
add_executable(EventQueue ${SRC_FILES} ${HEADER_FILES})
target_link_libraries(EventQueue Qt::Widgets)

@ -1,6 +0,0 @@
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}

@ -0,0 +1,16 @@
#include "Audio.h"
#include <iostream>
void Audio::update() {
auto cmd = pop();
// use volume, soundId to play sound
delete cmd;
}
void Audio::playSound(double volume, unsigned int soundId) {
auto command = new AudioCommand {volume, soundId};
push(command);
}

@ -0,0 +1,14 @@
#pragma once
#include "Queue.h"
struct AudioCommand {
double volume;
unsigned soundId;
};
class Audio : private Queue<AudioCommand> {
void update() override;
public:
void playSound(double volume, unsigned soundId);
};

@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <QEvent>
struct InputEvent{
QEvent::Type type;
};
struct GameEvent {
int time = 0;
virtual void print() {};
};
struct CoinCollectEvent : GameEvent {
double value = 0;
};
struct DamageEvent : GameEvent {
double amount = 0;
};

@ -0,0 +1,30 @@
#include "FileManager.h"
#include <iostream>
void FileManager::update() {
auto cmd = pop();
cmd->execute();
delete cmd;
}
void FileManager::readFile(const std::string &path, const std::function<void(std::string)> &readCallback) {
auto cmd = new FileReadCommand;
cmd->path = path;
cmd->readCallback = readCallback;
push(cmd);
}
void FileManager::writeFile(const std::string &path, const std::string &content) {
auto cmd = new FileWriteCommand;
cmd->path = path;
cmd->content = content;
push(cmd);
}
void FileReadCommand::execute() {
}
void FileWriteCommand::execute() {
}

@ -0,0 +1,25 @@
#pragma once
#include "Queue.h"
struct FileCommand {
std::string path;
virtual void execute() {};
};
struct FileReadCommand : FileCommand {
std::function<void(std::string)> readCallback;
void execute() override;
};
struct FileWriteCommand : FileCommand {
std::string content;
void execute() override;
};
class FileManager : private Queue<FileCommand>{
void update() override;
public:
void readFile(const std::string &path, const std::function<void(std::string)> &readCallback);
void writeFile(const std::string &path, const std::string &content);
};

@ -0,0 +1,17 @@
#pragma once
template <typename EventType>
class Listener {
protected:
template <typename T>
bool isType(EventType * event) {
return cast<T>(event);
}
template <typename T>
T * cast(EventType * event) {
return dynamic_cast<T *>(event);
}
public:
virtual bool wantsEvent(EventType *) { return true; }
virtual void accept(EventType *) {}
};

@ -0,0 +1,22 @@
#include "Player.h"
#include <iostream>
bool Player::wantsEvent(GameEvent * event) {
return isType<CoinCollectEvent>(event) || isType<DamageEvent>(event);
}
void Player::accept(GameEvent *event) {
if (auto coinEvent = cast<CoinCollectEvent>(event))
OnCoinCollect(coinEvent);
if (auto dmgEvent = cast<DamageEvent>(event))
OnDamage(dmgEvent);
}
void Player::OnCoinCollect(CoinCollectEvent *event) {
std::cout << event->value << std::endl;
}
void Player::OnDamage(DamageEvent *event) {
std::cout << event->amount << std::endl;
}

@ -0,0 +1,13 @@
#pragma once
#include "Listener.h"
#include "Event.h"
class Player : public Listener<GameEvent> {
public:
bool wantsEvent(GameEvent * event) override;
void accept(GameEvent * event) override;
protected:
void OnCoinCollect(CoinCollectEvent * event);
void OnDamage(DamageEvent * event);
};

@ -0,0 +1,74 @@
#pragma once
#include <vector>
#include "Event.h"
#include "Listener.h"
#include <thread>
#include <QApplication>
#include <mutex>
template<typename T>
class Queue {
private:
std::thread thread;
std::mutex mutex;
void run() {
while (!QApplication::closingDown()){
if (!container.empty())
update();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
};
virtual void update() {}
std::vector<T *> container;
protected:
size_t size() const {
return container.size();
}
T * pop(){
mutex.lock();
T * element = container.back();
container.pop_back();
mutex.unlock();
return element;
}
public:
Queue(){
thread = std::thread(&Queue::run, this);
}
void push(T * element){
mutex.lock();
container.insert(container.begin(), element);
mutex.unlock();
}
};
template <typename EventType>
class EventQueue : protected Queue<EventType>{
std::vector<Listener<EventType> *> listeners;
void update() override {
EventType * event = this->pop();
for (auto listener : listeners)
if (listener->wantsEvent(event))
listener->accept(event);
delete event;
}
public:
template <typename T>
void submitEvent(T * event){
this->push(event);
}
void registerListener(Listener<EventType> * listener){
listeners.push_back(listener);
}
void unregisterListener(Listener<EventType> * listener){
std::remove(listeners.begin(), listeners.end(), listener);
}
};
using InputQueue = EventQueue<InputEvent>;
using GameQueue = EventQueue<GameEvent>;

@ -0,0 +1,43 @@
#include <QApplication>
#include <QWidget>
#include <iostream>
#include "Queue.h"
#include "Audio.h"
#include "FileManager.h"
#include "Player.h"
using std::cout, std::endl;
auto audioManager = new Audio;
auto fileManager = new FileManager;
auto gameQueue = new GameQueue;
auto inputQueue = new InputQueue;
int main(int argc, char * argv[]){
QApplication app(argc, argv);
/*
for (int i = 0; i < 100'000; i++)
audioManager->playSound(1, i);
*/
/*
for (int i = 0; i < 10'000; i++){
fileManager->readFile("path" + std::to_string(i), [](const std::string& content){
std::cout << content << std::endl;
});
fileManager->writeFile("path" + std::to_string(i), "some content" + std::to_string(i));
}
*/
auto player = new Player;
gameQueue->registerListener(player);
gameQueue->submitEvent<CoinCollectEvent>(new CoinCollectEvent);
gameQueue->submitEvent<DamageEvent>(new DamageEvent);
inputQueue->submitEvent<InputEvent>(new InputEvent);
QWidget window;
window.show();
return QApplication::exec();
}
Loading…
Cancel
Save