Skip to content

Commit d49dfc7

Browse files
Merge branch 'main' into update-copyright-1.0-to-main
2 parents d78e517 + 62de012 commit d49dfc7

File tree

16 files changed

+977
-186
lines changed

16 files changed

+977
-186
lines changed

.github/workflows/build.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
name: CI
6+
7+
on: [push, pull_request]
8+
9+
jobs:
10+
build:
11+
runs-on: ${{ matrix.os }}
12+
strategy:
13+
fail-fast: true
14+
matrix:
15+
os:
16+
- ubuntu-22.04
17+
#- ubuntu-20.04
18+
- windows-2022
19+
#- windows-2019
20+
- macos-12
21+
#- macos-11
22+
build_type:
23+
- Debug
24+
- Release
25+
26+
steps:
27+
- name: Checkout sources
28+
uses: actions/checkout@v4
29+
30+
- name: Create build directory
31+
run: mkdir build
32+
33+
- name: Install ninja-build tool
34+
uses: turtlesec-no/get-ninja@main
35+
36+
- name: Make sure MSVC is found when Ninja generator is in use
37+
uses: ilammy/msvc-dev-cmd@v1
38+
39+
- name: Configure project
40+
run: >
41+
cmake -S . -B ./build -G Ninja
42+
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
43+
-DKDBindings_TESTS=${{ matrix.build_type == 'Debug' }}
44+
-DKDBindings_EXAMPLES=${{ matrix.build_type == 'Debug' }}
45+
-DKDBindings_DOCS=${{ matrix.build_type == 'Debug' && runner.os == 'Linux' }}
46+
47+
- name: Build Project
48+
run: cmake --build ./build
49+
50+
- name: Run tests
51+
if: ${{ matrix.build_type == 'Debug' }}
52+
run: ctest --test-dir ./build -C ${{ matrix.build_type }} --output-on-failure
53+
54+
- name: Read tests log when it fails
55+
uses: andstor/file-reader-action@v1
56+
if: ${{ failure() && matrix.build_type == 'Debug' }}
57+
with:
58+
path: "./build/Testing/Temporary/LastTest.log"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ imgui.ini
7979

8080
.vscode/*
8181
build/*
82+
build-*
8283
serenity_metatype.*
8384
output.json
8485

CMakeLists.txt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ cmake_minimum_required(VERSION 3.12) # for `project(... HOMEPAGE_URL ...)`
3131
project(KDBindings
3232
DESCRIPTION "Bindings, from the comfort and speed of C++ and without Qt"
3333
LANGUAGES CXX
34-
VERSION 1.0.1
34+
VERSION 1.0.95
3535
HOMEPAGE_URL "https://github.com/KDAB/KDBindings"
3636
)
3737

@@ -94,10 +94,6 @@ endif()
9494

9595
if(${PROJECT_NAME}_DOCS)
9696
add_subdirectory(docs) # needs to go last, in case there are build source files
97-
else()
98-
add_custom_target(docs
99-
COMMAND ${CMAKE_COMMAND} -E echo "Sorry, there is no docs target since KDBindings_DOCS=OFF."
100-
"Re-run cmake with the -DKDBindings_DOCS=ON option if you want to generate the documentation.")
10197
endif()
10298

10399
if(${PROJECT_NAME}_IS_ROOT_PROJECT)

CMakePresets.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"version": 2,
3+
"configurePresets": [
4+
{
5+
"name": "dev",
6+
"displayName": "dev",
7+
"generator": "Ninja",
8+
"binaryDir": "${sourceDir}/build-dev",
9+
"cacheVariables": {
10+
"CMAKE_BUILD_TYPE": "Debug",
11+
"CMAKE_EXPORT_COMPILE_COMMANDS" : "ON",
12+
"KDBindings_TESTS" : "ON",
13+
"KDBindings_EXAMPLES" : "ON"
14+
}
15+
}
16+
]
17+
}

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
* v1.1.0 (unreleased)
2+
- Feature: Add ScopedConnection for RAII-style connection management (#31)
3+
14
* v1.0.1
25
- Property: Make moved Signal private (#24 & #26) - BREAKING!
36
- Documentation: Small fixes & updates
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# This file is part of KDBindings.
2+
#
3+
# SPDX-FileCopyrightText: 2021-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
4+
# Author: Leon Matthes <[email protected]>
5+
#
6+
# SPDX-License-Identifier: MIT
7+
#
8+
# Contact KDAB at <[email protected]> for commercial licensing options.
9+
#
10+
11+
project(08-managing-connections VERSION 0.1 LANGUAGES CXX)
12+
13+
add_executable(${PROJECT_NAME}
14+
main.cpp
15+
)
16+
target_link_libraries(${PROJECT_NAME} KDAB::KDBindings)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
This file is part of KDBindings.
3+
4+
SPDX-FileCopyrightText: 2021-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
5+
Author: Leon Matthes <[email protected]>
6+
7+
SPDX-License-Identifier: MIT
8+
9+
Contact KDAB at <[email protected]> for commercial licensing options.
10+
*/
11+
12+
#include <ios>
13+
#include <kdbindings/signal.h>
14+
15+
#include <iostream>
16+
#include <string>
17+
18+
using namespace KDBindings;
19+
20+
void displayLabelled(const std::string &label, int value)
21+
{
22+
std::cout << label << ": " << value << std::endl;
23+
}
24+
25+
int main()
26+
{
27+
Signal<int> signal;
28+
29+
{
30+
// A ScopedConnection will disconnect the connection once it goes out of scope.
31+
// It is especially useful if you're connecting to a member function.
32+
// Storing a ScopedConnection in the object that contains the slot ensures the connection
33+
// is disconnected when the object is destructed.
34+
// This ensures that there are no dangling connections.
35+
ScopedConnection guard = signal.connect(displayLabelled, "Guard is connected");
36+
37+
signal.emit(1);
38+
} // The connection is disconnected here
39+
40+
signal.emit(2);
41+
42+
ConnectionHandle handle = signal.connect(displayLabelled, "Connection is not blocked");
43+
44+
signal.emit(3);
45+
{
46+
// A ConnectionBlocker will block a connection for the duration of its scope.
47+
// This is a good way to avoid endless-recursion, or to suppress updates for a short time.
48+
ConnectionBlocker blocker(handle); // The connection is blocked here
49+
50+
signal.emit(4);
51+
} // The connection is un-blocked here
52+
53+
signal.emit(5);
54+
55+
return 0;
56+
}

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ add_subdirectory(04-simple-property)
1515
add_subdirectory(05-property-bindings)
1616
add_subdirectory(06-lazy-property-bindings)
1717
add_subdirectory(07-advanced-connections)
18+
add_subdirectory(08-managing-connections)

src/kdbindings/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ set(HEADERS
1717
property.h
1818
property_updater.h
1919
signal.h
20+
connection_evaluator.h
21+
connection_handle.h
2022
utils.h
2123
)
2224

src/kdbindings/connection_evaluator.h

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
This file is part of KDBindings.
3+
4+
SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
5+
Author: Shivam Kunwar <[email protected]>
6+
7+
SPDX-License-Identifier: MIT
8+
9+
Contact KDAB at <[email protected]> for commercial licensing options.
10+
*/
11+
#pragma once
12+
13+
#include <functional>
14+
#include <mutex>
15+
16+
#include <kdbindings/connection_handle.h>
17+
18+
namespace KDBindings {
19+
20+
/**
21+
* @brief Manages and evaluates deferred Signal connections.
22+
*
23+
* @warning Deferred connections are experimental and may be removed or changed in the future.
24+
*
25+
* The ConnectionEvaluator class is responsible for managing and evaluating connections
26+
* to Signals. It provides mechanisms to delay and control the evaluation of connections.
27+
* It therefore allows controlling when and on which thread slots connected to a Signal are executed.
28+
*
29+
* @see Signal::connectDeferred()
30+
*/
31+
class ConnectionEvaluator
32+
{
33+
34+
public:
35+
/** ConnectionEvaluators are default constructible */
36+
ConnectionEvaluator() = default;
37+
38+
/** Connectionevaluators are not copyable */
39+
// As it is designed to manage connections,
40+
// and copying it could lead to unexpected behavior, including duplication of connections and issues
41+
// related to connection lifetimes. Therefore, it is intentionally made non-copyable.
42+
ConnectionEvaluator(const ConnectionEvaluator &) noexcept = delete;
43+
44+
ConnectionEvaluator &operator=(const ConnectionEvaluator &) noexcept = delete;
45+
46+
/** ConnectionEvaluators are not moveable */
47+
// As they are captures by-reference
48+
// by the Signal, so moving them would lead to a dangling reference.
49+
ConnectionEvaluator(ConnectionEvaluator &&other) noexcept = delete;
50+
51+
ConnectionEvaluator &operator=(ConnectionEvaluator &&other) noexcept = delete;
52+
53+
/**
54+
* @brief Evaluate the deferred connections.
55+
*
56+
* This function is responsible for evaluating and executing deferred connections.
57+
* This function is thread safe.
58+
*/
59+
void evaluateDeferredConnections()
60+
{
61+
std::lock_guard<std::mutex> lock(m_slotInvocationMutex);
62+
63+
for (auto &pair : m_deferredSlotInvocations) {
64+
pair.second();
65+
}
66+
m_deferredSlotInvocations.clear();
67+
}
68+
69+
private:
70+
template<typename...>
71+
friend class Signal;
72+
73+
void enqueueSlotInvocation(const ConnectionHandle &handle, const std::function<void()> &slotInvocation)
74+
{
75+
std::lock_guard<std::mutex> lock(m_slotInvocationMutex);
76+
m_deferredSlotInvocations.push_back({ handle, std::move(slotInvocation) });
77+
}
78+
79+
void dequeueSlotInvocation(const ConnectionHandle &handle)
80+
{
81+
std::lock_guard<std::mutex> lock(m_slotInvocationMutex);
82+
83+
auto handleMatches = [&handle](const auto &invocationPair) {
84+
return invocationPair.first == handle;
85+
};
86+
87+
// Remove all invocations that match the handle
88+
m_deferredSlotInvocations.erase(
89+
std::remove_if(m_deferredSlotInvocations.begin(), m_deferredSlotInvocations.end(), handleMatches),
90+
m_deferredSlotInvocations.end());
91+
}
92+
93+
std::vector<std::pair<ConnectionHandle, std::function<void()>>> m_deferredSlotInvocations;
94+
std::mutex m_slotInvocationMutex;
95+
};
96+
} // namespace KDBindings

0 commit comments

Comments
 (0)