Skip to content

Commit 96b8279

Browse files
author
Levent KARAGÖL
committed
Event Hub infrastructure has been committed
1 parent 3cc6806 commit 96b8279

6 files changed

Lines changed: 304 additions & 0 deletions

File tree

.github/workflows/linux.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: linux
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
container:
16+
image: ubuntu:24.04
17+
18+
steps:
19+
- name: Enable core dumps
20+
run: ulimit -c unlimited
21+
- uses: actions/checkout@v3
22+
- name: Install prerequisites
23+
run: |
24+
apt update
25+
apt install -y build-essential g++ make cmake pkg-config git wget curl zip unzip tar gdb
26+
- name: Install vcpkg
27+
run: |
28+
git clone https://github.com/microsoft/vcpkg.git /opt/vcpkg
29+
/opt/vcpkg/bootstrap-vcpkg.sh
30+
ln -s /opt/vcpkg/vcpkg /usr/local/bin/vcpkg
31+
- name: Clone project repository
32+
run: |
33+
git clone https://github.com/leventkaragol/libcpp-event-hub.git /root/libcpp-event-hub
34+
- name: Run cmake with vcpkg toolchain
35+
run: |
36+
cd /root/libcpp-event-hub
37+
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake
38+
- name: Build the project
39+
run: |
40+
cd /root/libcpp-event-hub
41+
cmake --build build --config Release
42+
- name: Run tests with gdb
43+
run: |
44+
cd /root/libcpp-event-hub
45+
gdb -ex "run" -ex "bt" -ex "quit" --args ./build/test/test

.github/workflows/windows.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: windows
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
jobs:
13+
test:
14+
runs-on: windows-latest
15+
steps:
16+
- uses: actions/checkout@v3
17+
18+
- name: Set up environment
19+
run: |
20+
choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
21+
choco install git
22+
choco install ninja
23+
24+
- name: Install vcpkg
25+
run: |
26+
if (Test-Path "C:\vcpkg") {
27+
Remove-Item "C:\vcpkg" -Recurse -Force
28+
}
29+
git clone https://github.com/microsoft/vcpkg.git C:\vcpkg
30+
& "C:\vcpkg\bootstrap-vcpkg.bat"
31+
echo "VCPKG_ROOT=C:\vcpkg" | Out-File -Append -Encoding ascii $env:GITHUB_ENV
32+
33+
- name: Integrate vcpkg
34+
run: |
35+
$env:VCPKG_ROOT = "C:\vcpkg"
36+
& "$env:VCPKG_ROOT\vcpkg" integrate install
37+
38+
- name: Install dependencies
39+
run: |
40+
$env:VCPKG_ROOT = "C:\vcpkg"
41+
cd $env:GITHUB_WORKSPACE
42+
& "$env:VCPKG_ROOT\vcpkg" install
43+
44+
- name: Prepare build environment
45+
run: |
46+
$env:CMAKE_TOOLCHAIN_FILE="${env:VCPKG_ROOT}\scripts\buildsystems\vcpkg.cmake"
47+
echo "CMAKE_TOOLCHAIN_FILE=${env:CMAKE_TOOLCHAIN_FILE}" | Out-File -Append -Encoding ascii $env:GITHUB_ENV
48+
echo "CMAKE_TOOLCHAIN_FILE is set to ${env:CMAKE_TOOLCHAIN_FILE}"
49+
50+
- name: Configure CMake project
51+
run: |
52+
echo "Using CMAKE_TOOLCHAIN_FILE: ${env:CMAKE_TOOLCHAIN_FILE}"
53+
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="${env:CMAKE_TOOLCHAIN_FILE}"
54+
55+
- name: Build the project
56+
run: |
57+
cmake --build build --config Release
58+
59+
- name: Run tests
60+
run: |
61+
& "D:\a\libcpp-event-hub\libcpp-event-hub\build\test\Release\test.exe"

.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,23 @@
3030
*.exe
3131
*.out
3232
*.app
33+
34+
## JetBrains IDE artifacts
35+
.idea
36+
cmake-build-*
37+
38+
## Visual Studio artifacts
39+
.vs
40+
ipch
41+
*.opensdf
42+
*.log
43+
*.pdb
44+
*.ilk
45+
*.user
46+
*.sdf
47+
*.suo
48+
*.VC.db
49+
*.VC.VC.opendb
50+
51+
## OSX artifacts
52+
.DS_Store

CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
cmake_minimum_required(VERSION 3.14)
2+
3+
project(libcpp-event-hub)
4+
5+
set(CMAKE_CXX_STANDARD 17)
6+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7+
8+
add_library(libcpp-event-hub INTERFACE)
9+
10+
target_include_directories(libcpp-event-hub INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src)
11+
12+
add_subdirectory(examples)
13+
add_subdirectory(test)

src/libcpp-event-hub.hpp

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
3+
Thread-safe generic event library for C++ (17+)
4+
version 1.0.0
5+
https://github.com/leventkaragol/libcpp-event-hub
6+
7+
If you encounter any issues, please submit a ticket at https://github.com/leventkaragol/libcpp-event-hub/issues
8+
9+
Copyright (c) 2024 Levent KARAGÖL
10+
11+
Permission is hereby granted, free of charge, to any person obtaining a copy
12+
of this software and associated documentation files (the "Software"), to deal
13+
in the Software without restriction, including without limitation the rights
14+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
copies of the Software, and to permit persons to whom the Software is
16+
furnished to do so, subject to the following conditions:
17+
18+
The above copyright notice and this permission notice shall be included in all
19+
copies or substantial portions of the Software.
20+
21+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
SOFTWARE.
28+
29+
*/
30+
31+
#ifndef LIBCPP_EVENT_HUB_HPP
32+
#define LIBCPP_EVENT_HUB_HPP
33+
34+
#include <string>
35+
#include <unordered_map>
36+
#include <functional>
37+
#include <shared_mutex>
38+
#include <any>
39+
#include <iostream>
40+
41+
namespace lklibs
42+
{
43+
/**
44+
* @brief Thread-safe generic Event hub class
45+
*/
46+
class EventHub
47+
{
48+
public:
49+
using ListenerFunction = std::function<void(const std::string&, const std::string&, const std::any&)>;
50+
51+
using ListenerId = size_t;
52+
53+
/**
54+
* @brief Get the singleton instance of the EventHub
55+
*
56+
* @return EventHub&
57+
*/
58+
static EventHub& getInstance()
59+
{
60+
static EventHub instance;
61+
return instance;
62+
}
63+
64+
/**
65+
* @brief Emit an event with generic type
66+
*
67+
* @tparam EventData: Type of the data to be sent with the event
68+
* @param eventName: Name of the event
69+
* @param sender: Sender of the event
70+
* @param data: Data to be sent with the event
71+
*/
72+
template <typename EventData>
73+
void emit(const std::string& eventName, const std::string& sender, const EventData& data)
74+
{
75+
std::shared_lock lock(mutex_);
76+
77+
std::any eventData = data;
78+
79+
if (listeners_.find(eventName) != listeners_.end())
80+
{
81+
for (const auto& [id, listener] : listeners_.at(eventName))
82+
{
83+
listener(eventName, sender, eventData);
84+
}
85+
}
86+
87+
if (listeners_.find("*") != listeners_.end())
88+
{
89+
for (const auto& [id, listener] : listeners_.at("*"))
90+
{
91+
listener(eventName, sender, eventData);
92+
}
93+
}
94+
}
95+
96+
/**
97+
* @brief Add a listener for an event
98+
*
99+
* @tparam EventData: Type of the data to be sent with the event
100+
* @param eventName: Name of the event
101+
* @param listener: Listener function to be called when the event is emitted
102+
* @return Listener Id
103+
*/
104+
template <typename EventData>
105+
ListenerId addListener(const std::string& eventName, std::function<void(const std::string&, const std::string&, const EventData&)> listener)
106+
{
107+
std::unique_lock lock(mutex_);
108+
109+
auto id = nextListenerId_++;
110+
111+
auto wrappedListener = [listener](const std::string& eventName, const std::string& sender, const std::any& data)
112+
{
113+
if (data.type() == typeid(EventData))
114+
{
115+
listener(eventName, sender, std::any_cast<const EventData&>(data));
116+
}
117+
};
118+
119+
listeners_[eventName][id] = wrappedListener;
120+
121+
return id;
122+
}
123+
124+
/**
125+
* @brief Remove a listener for an event
126+
*
127+
* @param eventName: Name of the event
128+
* @param listenerId: Id of the listener to be removed
129+
*/
130+
void removeListener(const std::string& eventName, ListenerId listenerId)
131+
{
132+
std::unique_lock lock(mutex_);
133+
134+
if (listeners_.find(eventName) != listeners_.end())
135+
{
136+
listeners_[eventName].erase(listenerId);
137+
138+
if (listeners_[eventName].empty())
139+
{
140+
listeners_.erase(eventName);
141+
}
142+
}
143+
}
144+
145+
private:
146+
EventHub() = default;
147+
EventHub(const EventHub&) = delete;
148+
EventHub& operator=(const EventHub&) = delete;
149+
150+
std::unordered_map<std::string, std::unordered_map<ListenerId, ListenerFunction>> listeners_;
151+
mutable std::shared_mutex mutex_;
152+
ListenerId nextListenerId_ = 0;
153+
};
154+
}
155+
156+
#endif // LIBCPP_EVENT_HUB_HPP

vcpkg.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name" : "libcpp-event-hub",
3+
"version-string" : "1.0.0",
4+
"builtin-baseline" : "7eb700c9688daed6d8bdcdc571ebe3eedea6a774",
5+
"dependencies" : [ {
6+
"name" : "gtest",
7+
"version>=" : "1.14.0#1"
8+
} ]
9+
}

0 commit comments

Comments
 (0)