### Create and Emit Signals in C++ with vdk-signals Source: https://context7.com/vdksoft/signals/llms.txt Demonstrates the basic API for creating signals with a specific signature and emitting them to connected slots. Supports function pointers, functors, member functions, and lambdas. Includes connection and emission examples. ```cpp #include #include using vdk::signal; void function(int arg) { std::cout << "function(" << arg << ")" << std::endl; } struct functor { explicit functor(int data) noexcept : data_{ data } {} void operator()(int arg) { std::cout << "functor(" << arg << ")" << std::endl; } bool operator==(const functor& other) const noexcept { return data_ == other.data_; } int data_; }; class demo_class { public: void method(int arg) { std::cout << "demo_class::method(" << arg << ")" << std::endl; } }; int main() { // Create signal with signature void(int) signal sig; // Connect function pointer sig.connect(function); // Connect function object sig.connect(functor{ 5 }); // Connect member function demo_class object; sig.connect(&object, &demo_class::method); // Connect lambda (returns connection ID for disconnection) auto id = sig.connect([](int arg) { std::cout << "lambda(" << arg << ")" << std::endl; }); // Emit signal - all connected slots are invoked sig.emit(42); // Alternative syntax sig(42); return 0; } ``` -------------------------------- ### C++ Processing Queued Signal Calls Source: https://context7.com/vdksoft/signals/llms.txt Demonstrates processing queued asynchronous signal calls using the VDKSoft signals library. This example connects a slot with asynchronous execution, emits signals, and then executes the queued calls to demonstrate event loop integration. ```cpp #include #include #include using vdk::signal; using vdk::context; using vdk::exec; using vdk::signals_execute; class receiver : public context { public: void on_message(int value) { std::cout << "Received: " << value << " in thread: " << std::this_thread::get_id() << std::endl; } }; int main() { signal sig; receiver recv; // Connect with async execution sig.connect(&recv, &receiver::on_message, exec::async); std::cout << "Main thread: " << std::this_thread::get_id() << std::endl; // Emit signal - queues async call sig.emit(42); // Execute one queued call if (signals_execute()) { std::cout << "Executed 1 call\n"; } // Queue multiple calls sig.emit(1); sig.emit(2); sig.emit(3); // Execute up to 2 calls int executed = 0; while (executed < 2 && signals_execute(1)) { ++executed; } std::cout << "Executed " << executed << " calls\n"; // Process all remaining calls while (signals_execute()) { // Empty - just executing } // Typical event loop pattern bool running = true; int loop_count = 0; while (running && loop_count < 10) { // Process queued signal calls signals_execute(); // Do other work... if (++loop_count >= 10) { running = false; } } return 0; } ``` -------------------------------- ### Custom Memory Resource for C++ Signals Library Source: https://context7.com/vdksoft/signals/llms.txt Illustrates how to install a custom memory allocator for the vdk-signals library. By inheriting from 'vdk::memory::signals::memory_resource' and overriding 'allocate' and 'deallocate' methods, users can control memory management for signal objects. This is useful for performance optimization or integration with custom memory pools. ```cpp #include #include #include // Custom memory resource implementation class custom_memory : public vdk::memory::signals::memory_resource { public: void* allocate(std::size_t size, std::size_t align) override { std::cout << "Allocating " << size << " bytes (align: " << align << ")" << std::endl; void* ptr = std::aligned_alloc(align, size); if (!ptr) { throw std::bad_alloc(); } return ptr; } void deallocate(void* addr, std::size_t size, std::size_t align) noexcept override { std::cout << "Deallocating " << size << " bytes (align: " << align << ")" << std::endl; std::free(addr); } }; int main() { // Install custom memory resource (can only be done once) static custom_memory mem_resource; vdk::memory::signals::memory(&mem_resource); // Now all library allocations use custom memory resource vdk::signal sig; // Output: "Allocating ... bytes ..." sig.connect([](int x) { std::cout << "Value: " << x << std::endl; }); // Output: "Allocating ... bytes ..." sig.emit(42); // Output: "Value: 42" sig.disconnect(); // Output: "Deallocating ... bytes ..." // sig destructor will trigger more deallocations // Output: "Deallocating ... bytes ..." return 0; } ``` -------------------------------- ### C++ Cross-Thread Signal Emissions Source: https://context7.com/vdksoft/signals/llms.txt Demonstrates cross-thread signal emissions with automatic thread affinity and asynchronous execution using the VDKSoft signals library. This example connects slots to a signal and emits the signal from a different thread, showcasing asynchronous execution and thread affinity management. ```cpp #include #include #include #include using vdk::signal; using vdk::context; using vdk::exec; using vdk::signals_execute; void function(int arg1, int arg2) { std::cout << "function(" << arg1 << ", " << arg2 << ") thread:\" << std::this_thread::get_id() << \"\n"; } struct functor { explicit functor(int data) : data_{ data } {} void operator()(int arg1, int arg2) { std::cout << "functor(" << arg1 << ", " << arg2 << ") thread:\" << std::this_thread::get_id() << \"\n"; } bool operator==(const functor& other) const { return data_ == other.data_; } int data_; }; class demo_class : public context { public: void method(int arg1, int arg2) { std::cout << "method(" << arg1 << ", " << arg2 << ") thread:\" << std::this_thread::get_id() << \"\n"; } }; int main() { signal sig; std::atomic_bool ready = false; // Worker thread with its own context std::thread worker([&sig, &ready] { // Context object created in worker thread demo_class object; // Connect slots - they will execute in this thread sig.connect(&object, &demo_class::method); sig.connect(&object, function); sig.connect(&object, functor{ 4 }); sig.connect(&object, [](int a, int b) { std::cout << "lambda(" << a << ", " << b << ") thread:\" << std::this_thread::get_id() << \"\n"; }); ready = true; // Event loop - processes cross-thread signal emissions // This extracts and executes slot calls received in this thread int call_count = 0; while (call_count < 4) { if (signals_execute()) { ++call_count; } } // When thread exits, all associated slots auto-disconnect }); // Wait for worker thread setup while (!ready.load()) { std::this_thread::yield(); } std::cout << "Emitting from main thread: " << std::this_thread::get_id() << std::endl; // Emit from main thread - slots execute in worker thread sig.emit(5, 10); worker.join(); // Explicit execution type control demo_class object; // Force asynchronous execution (even from same thread) sig.connect(&object, functor{ 1 }, exec::async); // Force synchronous execution (even from different thread) sig.connect(&object, function, exec::sync); std::cout << "Emitting from thread: " << std::this_thread::get_id() << std::endl; sig.emit(100, 200); // exec::sync slot called immediately // exec::async slot queued for signals_execute() // Process async calls in current thread signals_execute(); return 0; } ``` -------------------------------- ### Configure CMake project for signals library Source: https://github.com/vdksoft/signals/blob/master/CMakeLists.txt This snippet sets up a CMake project for the signals library, specifying C++17 as the required standard and configuring compiler warnings for different compilers. It also includes source files and links against the system's thread library. ```CMake cmake_minimum_required(VERSION 3.8) project(signals CXX) enable_testing() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) add_library(signals "") target_sources(signals PRIVATE ${CMAKE_SOURCE_DIR}/src/signals.h ${CMAKE_SOURCE_DIR}/src/signals.cpp) target_include_directories(signals PUBLIC ${CMAKE_SOURCE_DIR}/src) target_compile_options(signals PUBLIC $<$:-Wall> $<$:-Wall> $<$:-Wall> $<$:/W4>) find_package (Threads) target_link_libraries (signals PUBLIC ${CMAKE_THREAD_LIBS_INIT}) add_subdirectory(tests) add_subdirectory(demo) ``` -------------------------------- ### Configure CMake Test Suite with Google Test Source: https://github.com/vdksoft/signals/blob/master/tests/CMakeLists.txt Configures a C++ test suite using Google Test framework with automated dependency management. Creates a signals-test executable from tests.cpp, links against gtest_main and signals libraries, and registers the test with CTest. Requires CMake 3.8+ and uses C++17 standard. ```cmake cmake_minimum_required(VERSION 3.8) project(signals-test CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(GTEST_SOURCE_DIR "" CACHE PATH "Path to Google Test sources") set(GTEST_WORKING_DIR "${CMAKE_BINARY_DIR}/googletest") if (NOT EXISTS "${GTEST_SOURCE_DIR}") set(GTEST_SOURCE_DIR "${GTEST_WORKING_DIR}/src" CACHE PATH "Path to Google Test sources" FORCE) configure_file("${CMAKE_CURRENT_LIST_DIR}/CMakeLists.in" "${GTEST_WORKING_DIR}/tmp/CMakeLists.txt") execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY "${GTEST_WORKING_DIR}/tmp") execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${GTEST_WORKING_DIR}/tmp") endif() set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) add_subdirectory("${GTEST_SOURCE_DIR}" "${GTEST_WORKING_DIR}/build") add_executable(signals-test "tests.cpp") target_link_libraries(signals-test gtest_main signals) add_test(signals-test signals-test) ``` -------------------------------- ### Signal Construction and Destruction Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Defines the constructor and destructor for the signal object. The constructor initializes a new signal, and the destructor cleans up by disconnecting all associated slots. Special handling is included for destruction during signal emission. ```cpp signal(); ~signal() noexcept; ``` -------------------------------- ### Lite Version Signals for Single-Threaded C++ Applications Source: https://context7.com/vdksoft/signals/llms.txt Demonstrates the usage of the lightweight 'vdk::lite::signal' for single-threaded applications. This version bypasses thread-safety overhead, offering synchronous slot execution without explicit execution types. It showcases connecting functions, class member functions, and lambdas, along with emitting, blocking, and disconnecting signals. ```cpp #include #include #include // Use lite namespace for single-threaded version using vdk::lite::signal; using vdk::lite::context; void function(const std::string& msg) { std::cout << "function: " << msg << std::endl; } class receiver : public context { public: void on_event(const std::string& msg) { std::cout << "receiver: " << msg << std::endl; } }; int main() { // Lite signal - same API, no thread-safety overhead signal sig; receiver recv; // Connect slots (no exec type - always synchronous) sig.connect(function); sig.connect(&recv, &receiver::on_event); sig.connect(&recv, [](const std::string& msg) { std::cout << "lambda: " << msg << std::endl; }); // Emit signal - all slots execute synchronously sig.emit("test event"); // Output: // function: test event // receiver: test event // lambda: test event // Blocking works the same sig.block(); sig.emit("blocked"); // Nothing happens sig.block(false); // Disconnection works the same sig.disconnect(function); sig.disconnect(&recv, &receiver::on_event); // Context lifetime tracking works the same { receiver temp; sig.connect(&temp, &receiver::on_event); sig.emit("with temp"); // temp.on_event called } sig.emit("without temp"); // temp destroyed, slot auto-disconnected return 0; } ``` -------------------------------- ### Connecting Slots to Signals Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Provides methods to connect callable slots to a signal. Supports connecting object-method pairs, context-callable pairs, and standalone callables. Returns a connection ID for later disconnection. Throws exceptions on memory allocation failure. ```cpp template unsigned connect(Ty * object, Fn slot, exec type = {}); template unsigned connect(Fn slot); ``` -------------------------------- ### Emitting Signals Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md The `emit` method and the `operator()` overload are used to trigger the signal and invoke all connected slots. Slots are invoked synchronously or asynchronously based on context and connection type. The emission process stops immediately if the signal is destroyed during invocation. ```cpp void emit(ArgTs ... args) const; void operator()(ArgTs ... args) const; ``` -------------------------------- ### Block and Unblock Signals in C++ Source: https://context7.com/vdksoft/signals/llms.txt Demonstrates how to temporarily prevent signal emissions using the `block()` and `unblock()` (or by calling `block(false)`) methods. It shows how to check the current blocking state and how emitted signals are ignored when blocked. ```cpp #include #include using vdk::signal; void function(int arg) { std::cout << "Received: " << arg << std::endl; } int main() { signal sig; sig.connect(function); // Check if signal is blocked if (!sig.blocked()) { std::cout << "Signal is not blocked\n"; } // Block the signal (returns previous blocking state) bool was_blocked = sig.block(); std::cout << "Was blocked before: " << was_blocked << std::endl; if (sig.blocked()) { std::cout << "Signal is now blocked\n"; } // This emission does nothing - signal is blocked sig.emit(100); // Unblock the signal was_blocked = sig.block(false); std::cout << "Was blocked: " << was_blocked << std::endl; if (!sig.blocked()) { std::cout << "Signal is not blocked\n"; } // Signal works normally now sig.emit(200); // Output: "Received: 200" return 0; } ``` -------------------------------- ### Disconnect Slots in C++ with vdk-signals Source: https://context7.com/vdksoft/signals/llms.txt Illustrates various methods for disconnecting slots from a signal. Supports disconnection by value (for function pointers and functors), by member function pointer and object, and by connection ID (useful for lambdas). Also shows how to disconnect multiple identical connections and all connections. ```cpp #include #include using vdk::signal; void function(int arg) { std::cout << "function(" << arg << ")" << std::endl; } struct functor { explicit functor(int data) noexcept : data_{ data } {} void operator()(int arg) { std::cout << "functor\n"; } bool operator==(const functor& other) const noexcept { return data_ == other.data_; } int data_; }; class demo_class { public: void method(int arg) { std::cout << "method\n"; } }; int main() { signal sig; sig.connect(function); sig.connect(functor{ 5 }); demo_class object; sig.connect(&object, &demo_class::method); auto lambda = [](int arg) { std::cout << "lambda\n"; }; auto id = sig.connect(lambda); // Disconnect by value (requires equality comparison operator) if (sig.disconnect(function)) { std::cout << "function disconnected\n"; } if (sig.disconnect(functor{ 5 })) { std::cout << "functor disconnected\n"; } // Disconnect member function (requires object pointer) if (sig.disconnect(&object, &demo_class::method)) { std::cout << "method disconnected\n"; } // Disconnect by ID (for lambdas without equality comparison) if (sig.disconnect(id)) { std::cout << "lambda disconnected\n"; } // Multiple identical connections sig.connect(function); sig.connect(function); sig.connect(function); sig.emit(1); // Calls function 3 times sig.disconnect(function); // Removes one connection sig.emit(2); // Calls function 2 times // Disconnect all remaining slots sig.disconnect(); sig.emit(3); // Nothing happens return 0; } ``` -------------------------------- ### Context Management in C++ Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Base class for managing context during slot invocations. It associates thread affinity and manages lifetime automatically. All operations on a context object should be performed within the thread it belongs to, ensuring serialized slot invocations and preventing race conditions. ```cpp class context { public: context(); ~context() noexcept; context(const context &) = delete; context(context &&) = delete; context & operator=(const context &) = delete; context & operator=(context &&) = delete; }; ``` -------------------------------- ### Object Lifetime Tracking with Context in C++ Source: https://context7.com/vdksoft/signals/llms.txt Illustrates how signals can automatically disconnect slots when the context object associated with them is destroyed. This is achieved by inheriting from `vdk::context` or by associating slots with an object pointer. It also shows explicit disconnection syntax. ```cpp #include #include #include using vdk::signal; using vdk::context; void function(const std::string& arg) { std::cout << "function(" << arg << ")" << std::endl; } struct functor { explicit functor(int data) : data_{ data } {} void operator()(const std::string& arg) { std::cout << "functor(" << arg << ")" << std::endl; } bool operator==(const functor& other) const { return data_ == other.data_; } int data_; }; // Inherit from context for automatic lifetime tracking class demo_class : public context { public: void method(const std::string& arg) { std::cout << "demo_class::method(" << arg << ")" << std::endl; } }; int main() { signal sig; { // Context object provides automatic tracking demo_class object; // Connect method slot sig.connect(&object, &demo_class::method); // Associate other callables with the context object sig.connect(&object, function); sig.connect(&object, functor{ 4 }); sig.connect(&object, [](const std::string& arg) { std::cout << "lambda(" << arg << ")" << std::endl; }); // All slots are invoked - object is alive sig.emit("hello"); // Output: 4 different slot invocations } // Context object destroyed - all associated slots auto-disconnected sig.emit("nothing"); // Output: Nothing (no slots are reachable) // Disconnection syntax for context-associated slots demo_class object2; sig.connect(&object2, &demo_class::method); sig.disconnect(&object2, &demo_class::method); // Provide object for method sig.connect(&object2, function); sig.disconnect(function); // No object needed for standalone callable sig.connect(&object2, functor{ 5 }); sig.disconnect(functor{ 5 }); // No object needed return 0; } ``` -------------------------------- ### Enum for Slot Execution Type in C++ Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Specifies the execution type for slots: `sync` for synchronous execution and `async` for asynchronous execution. Use with caution, as synchronous execution across different threads can lead to race conditions. ```cpp enum class exec { sync, async }; ``` -------------------------------- ### Signal Execution Control in C++ Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Executes pending signal emissions for the current thread. Can execute at most one or a specified number of slot calls. This method does not block and integrates with event loops for handling cross-thread signal emissions. ```cpp bool signals_execute(); bool signals_execute(unsigned number); ``` -------------------------------- ### Check Signal Blocking Status in C++ Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Checks if a signal is currently blocked. Returns true if blocked, false otherwise. Note that this method provides an approximation and may not reflect the exact state in highly concurrent scenarios due to potential race conditions. ```cpp bool blocked() const noexcept; ``` -------------------------------- ### Disconnecting Slots from Signals Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Offers various methods to disconnect slots from a signal. Supports disconnection by object-method pair, by slot callable, by connection ID, or disconnecting all slots. Returns a boolean indicating success or failure. ```cpp template bool disconnect(Ty * object, Fn slot) noexcept; template bool disconnect(Fn slot) noexcept; template bool disconnect(unsigned id) noexcept; template void disconnect() noexcept; ``` -------------------------------- ### Block/Unblock Signal in C++ Source: https://github.com/vdksoft/signals/blob/master/docs/signals.md Controls whether a signal is blocked or unblocked. Returns true if the signal was previously blocked, false otherwise. This operation is lock-free unless an expired context is detected, requiring an internal lock for disconnection. ```cpp bool block(bool yes = true) noexcept; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.