commit 1692c0d3f91411abb5ad8c1b4cdf43bf49d922ef Author: josh Date: Wed Feb 21 22:56:32 2024 -0500 Initial Commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..64e0296 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.27) +project(Event + VERSION 1.0 + LANGUAGES CXX +) + +if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) + message(FATAL_ERROR "In-Source builds are not allowed") +endif() + +set(CMAKE_CXX_STANDARD 20) + +if (WIN32) + set(CMAKE_CXX_FLAGS "-municode") +endif() + +file(GLOB_RECURSE SOURCES "src/*.cpp") + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +include_directories("include") + +add_library(Event SHARED ${SOURCES} + src/Event.cpp) + +set_target_properties(Event PROPERTIES LINKER_LANGUAGE CXX) + +add_executable(EventDemo main.cpp) + +target_link_libraries(EventDemo PUBLIC Event) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/include/Event.h b/include/Event.h new file mode 100644 index 0000000..c3dfbfd --- /dev/null +++ b/include/Event.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include + +// TODO: Document & Explain this + +template +class Event; + +template +class EventConnection { +private: + using delegate = std::function; +public: + EventConnection(Event *creator, delegate cb) : owner(creator), callback(std::move(cb)) {} + bool Disconnect(); // Breaks the event connection, but does not destroy the instance + void Invoke(Args... e); +private: + Event * owner; + delegate callback; + bool active = true; +}; + +template +class Event { +public: + using delegate = std::function; + using connection = EventConnection; + using event_ptr = std::shared_ptr; +public: + void Await(Args& ... arg); + void Invoke(Args... args); + void operator()(Args... args); + connection Connect(delegate callback); + void Disconnect(connection &conn); + connection operator+=(delegate callback); +private: + std::vector listeners; + uint64_t listenerCounter = 0; +}; + + +template +EventConnection Event::operator+=(Event::delegate callback) { return Connect(callback); } + +template +void Event::operator()(Args... args) { Invoke(args...);} + +template +void EventConnection::Invoke(Args... e) { callback(e...); } + +template +bool EventConnection::Disconnect() { + if (active) { + owner->Disconnect(this); + active = false; + return true; + } + return false; +} + +template +void Event::Invoke(Args... args) { + for (event_ptr &connection_ptr: this->listeners) { + connection_ptr->Invoke(args...); + } +} + +template +EventConnection Event::Connect(delegate callback) +{ + event_ptr retval(new connection(this, callback)); + this->listeners.push_back(retval); + return *retval; +} + +template +void Event::Disconnect(connection &conn) { + listeners.erase(std::remove(listeners.begin(), listeners.end(), 99), listeners.end()); +} \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..a85b2ea --- /dev/null +++ b/main.cpp @@ -0,0 +1,30 @@ +#include + +#include + +void ProcessMessage(const std::string& message) +{ + std::cout << "Received: " << message << std::endl; +} + +int main() { + + Event OnMessage; + + bool run = true; + + auto handler = OnMessage += [&] (const std::string& message) + { + std::cout << "GOTS A MESSAGE: " << message << std::endl; + }; + auto handler2 = OnMessage += ProcessMessage; + + while (run) + { + std::string input; + std::cin >> input; + OnMessage.Invoke(input); + } + + return 0; +} diff --git a/src/Event.cpp b/src/Event.cpp new file mode 100644 index 0000000..b070ff3 --- /dev/null +++ b/src/Event.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file