{"id":21274166,"url":"https://github.com/endurodave/asyncmulticastdelegatecpp11","last_synced_at":"2025-07-11T06:33:52.612Z","repository":{"id":113549491,"uuid":"550294000","full_name":"endurodave/AsyncMulticastDelegateCpp11","owner":"endurodave","description":"Asynchronous Multicast Delegates in C++11","archived":false,"fork":false,"pushed_at":"2024-11-13T13:22:49.000Z","size":995,"stargazers_count":4,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-13T14:27:29.455Z","etag":null,"topics":["asynchronous-callbacks","asynchronous-programming","cpp","cpp11","cross-platform","delegates","embedded-systems","linux","multi-thread","multicast","publish-subscribe","windows"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/endurodave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-12T14:14:05.000Z","updated_at":"2024-11-13T13:22:53.000Z","dependencies_parsed_at":"2024-11-13T14:35:42.744Z","dependency_job_id":null,"html_url":"https://github.com/endurodave/AsyncMulticastDelegateCpp11","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endurodave%2FAsyncMulticastDelegateCpp11","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endurodave%2FAsyncMulticastDelegateCpp11/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endurodave%2FAsyncMulticastDelegateCpp11/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/endurodave%2FAsyncMulticastDelegateCpp11/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/endurodave","download_url":"https://codeload.github.com/endurodave/AsyncMulticastDelegateCpp11/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225701549,"owners_count":17510555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous-callbacks","asynchronous-programming","cpp","cpp11","cross-platform","delegates","embedded-systems","linux","multi-thread","multicast","publish-subscribe","windows"],"created_at":"2024-11-21T09:19:12.118Z","updated_at":"2025-07-11T06:33:52.603Z","avatar_url":"https://github.com/endurodave.png","language":"C++","readme":"# Asynchronous Multicast Delegates in C++\n\nA C++ delegate library capable of targeting any callable function synchronously or asynchronously.\n\n## ⚠️ Deprecated Repository\n\n\u003e **Warning:** This repository is no longer maintained. Please use the modern delegate library in link below.\n\n## New Repository \n\n[DelegateMQ](https://github.com/endurodave/DelegateMQ) - Invoke any C++ callable function synchronously, asynchronously, or on a remote endpoint.\n\n# Table of Contents\n\n- [Asynchronous Multicast Delegates in C++](#asynchronous-multicast-delegates-in-c)\n  - [⚠️ Deprecated Repository](#️-deprecated-repository)\n  - [New Repository](#new-repository)\n- [Table of Contents](#table-of-contents)\n- [Preface](#preface)\n  - [Related repositories](#related-repositories)\n  - [Library Comparison](#library-comparison)\n- [Introduction](#introduction)\n- [Delegates Background](#delegates-background)\n- [Quick Start](#quick-start)\n  - [Publisher](#publisher)\n  - [Subscriber](#subscriber)\n- [Project Build](#project-build)\n  - [Windows Visual Studio](#windows-visual-studio)\n  - [Linux Make](#linux-make)\n- [Using the Code](#using-the-code)\n  - [Synchronous Delegates](#synchronous-delegates)\n  - [Asynchronous Non-Blocking Delegates](#asynchronous-non-blocking-delegates)\n    - [Bind to std::shared\\_ptr](#bind-to-stdshared_ptr)\n    - [Caution Using Raw Object Pointers](#caution-using-raw-object-pointers)\n  - [Asynchronous Blocking Delegates](#asynchronous-blocking-delegates)\n  - [Asynchronous Lambda Invocation](#asynchronous-lambda-invocation)\n- [Delegate Library](#delegate-library)\n  - [Argument Heap Copy](#argument-heap-copy)\n  - [Bypassing Argument Heap Copy](#bypassing-argument-heap-copy)\n  - [Array Argument Heap Copy](#array-argument-heap-copy)\n  - [Worker Thread (Win32)](#worker-thread-win32)\n  - [Worker Thread (std::thread)](#worker-thread-stdthread)\n- [Delegate Invocation](#delegate-invocation)\n- [Delegate Containers](#delegate-containers)\n- [Examples](#examples)\n  - [SysData Example](#sysdata-example)\n  - [SysDataClient Example](#sysdataclient-example)\n  - [SysDataNoLock Example](#sysdatanolock-example)\n  - [SysDataNoLock Reinvoke Example](#sysdatanolock-reinvoke-example)\n  - [SysDataNoLock Blocking Reinvoke Example](#sysdatanolock-blocking-reinvoke-example)\n  - [Timer Example](#timer-example)\n- [Heap vs. Fixed Block](#heap-vs-fixed-block)\n- [Porting](#porting)\n- [Summary](#summary)\n- [Which Callback Implementation?](#which-callback-implementation)\n  - [Asynchronous Multicast Callbacks in C](#asynchronous-multicast-callbacks-in-c)\n  - [Asynchronous Multicast Callbacks with Inter-Thread Messaging](#asynchronous-multicast-callbacks-with-inter-thread-messaging)\n  - [Asynchronous Multicast Delegates in C++](#asynchronous-multicast-delegates-in-c-1)\n  - [Asynchronous Multicast Delegates in Modern C++](#asynchronous-multicast-delegates-in-modern-c)\n- [Conclusion](#conclusion)\n- [References](#references)\n\n\n# Preface\n\nOriginally published on CodeProject at: \u003ca href=\"http://www.codeproject.com/Articles/1160934/Asynchronous-Multicast-Delegates-in-Cplusplus\"\u003e\u003cstrong\u003eAsynchronous Multicast Delegates in C++\u003c/strong\u003e\u003c/a\u003e\n\n## Related repositories\n\n* \u003ca href=\"https://github.com/endurodave/AsyncStateMachine\"\u003eAsynchronous State Machine Design in C++\u003c/a\u003e - an asynchronous C++ state machine implemented using an asynchronous delegate library.\n* \u003ca href=\"https://github.com/endurodave/IntegrationTestFramework\"\u003eIntegration Test Framework using Google Test and Delegates\u003c/a\u003e - a multi-threaded C++ software integration test framework using Google Test and Delegate libraries.\n\n## Library Comparison\n\n\u003cp\u003eAsynchronous function invocation allows for easy movement of data between threads. The table below summarizes the various asynchronous function invocation implementations available in C and C++.\u003c/p\u003e\n\n| Repository                                                                                            | Language | Key Delegate Features                                                                                                                                                                                                               | Notes                                                                                                                                                                                                      |\n|-------------------------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| \u003ca href=\"https://github.com/endurodave/AsyncMulticastDelegateModern\"\u003eAsyncMulticastDelegateModern\u003c/a\u003e | C++17    | * Function-like template syntax\u003cbr\u003e * Any delegate target function type (member, static, free, lambda)\u003cbr\u003e  * N target function arguments\u003cbr\u003e * N delegate subscribers\u003cbr\u003e * Variadic templates\u003cbr\u003e * Template metaprogramming      | * Most generic implementation\u003cbr\u003e * Lowest lines of source code\u003cbr\u003e * Slowest of all implementations\u003cbr\u003e * Optional fixed block allocator support\u003cbr\u003e * No remote delegate support\u003cbr\u003e * Complex metaprogramming |\n| \u003ca href=\"https://github.com/endurodave/AsyncMulticastDelegateCpp17\"\u003eAsyncMulticastDelegateCpp17\u003c/a\u003e   | C++17    | * Function-like template syntax\u003cbr\u003e * Any delegate target function type (member, static, free, lambda)\u003cbr\u003e * 5 target function arguments\u003cbr\u003e * N delegate subscribers\u003cbr\u003e * Optional fixed block allocator\u003cbr\u003e * Variadic templates | * Selective compile using constexpr\u003cbr\u003e * Avoids complex metaprogramming\u003cbr\u003e * Faster than AsyncMulticastDelegateModern\u003cbr\u003e * No remote delegate support                                                   |\n| \u003ca href=\"https://github.com/endurodave/AsyncMulticastDelegateCpp11\"\u003eAsyncMulticastDelegateCpp11\u003c/a\u003e   | C++11    | * Function-like template syntax\u003cbr\u003e * Any delegate target function type (member, static, free, lambda)\u003cbr\u003e * 5 target function arguments\u003cbr\u003e * N delegate subscribers\u003cbr\u003e * Optional fixed block allocator                          | * High lines of source code\u003cbr\u003e * Highly repetitive source code                                                                                                                                            |\n| \u003ca href=\"https://github.com/endurodave/AsyncMulticastDelegate\"\u003eAsyncMulticastDelegate\u003c/a\u003e             | C++03    | * Traditional template syntax\u003cbr\u003e * Any delegate target function type (member, static, free)\u003cbr\u003e * 5 target function arguments\u003cbr\u003e * N delegate subscribers\u003cbr\u003e * Optional fixed block allocator                                    | * High lines of source code\u003cbr\u003e * Highly repetitive source code                                                                                                                                            |\n| \u003ca href=\"https://github.com/endurodave/AsyncCallback\"\u003eAsyncCallback\u003c/a\u003e                               | C++      | * Traditional template syntax\u003cbr\u003e * Delegate target function type (static, free)\u003cbr\u003e * 1 target function argument\u003cbr\u003e * N delegate subscribers                                                                                      | * Low lines of source code\u003cbr\u003e * Most compact C++ implementation\u003cbr\u003e * Any C++ compiler                                                                                                                    |\n| \u003ca href=\"https://github.com/endurodave/C_AsyncCallback\"\u003eC_AsyncCallback\u003c/a\u003e                           | C        | * Macros provide type-safety\u003cbr\u003e * Delegate target function type (static, free)\u003cbr\u003e * 1 target function argument\u003cbr\u003e * Fixed delegate subscribers (set at compile time)\u003cbr\u003e * Optional fixed block allocator                        | * Low lines of source code\u003cbr\u003e * Very compact implementation\u003cbr\u003e * Any C compiler                                                                                                                          |\n\n# Introduction\n\n\u003cp\u003eNothing seems to garner the interest of C++ programmers more than delegates. In other languages, the delegate is a first-class feature so developers can use these well-understood constructs. In C++, however, a delegate is not natively available. Yet that doesn\u0026rsquo;t stop us programmers from trying to emulate the ease with which a delegate stores and invokes any callable function.\u003c/p\u003e\n\n\u003cp\u003eDelegates normally support synchronous executions, that is, when invoked, the bound function is executed within the caller\u0026rsquo;s thread of control. On multi-threaded applications, it would be ideal to specify the target function and the thread it should execute on without imposing function signature limitations. The library does the grunt work of getting the delegate and all argument data onto the destination thread. The idea behind this article is to provide a C++ delegate library with a consistent API that is capable of synchronous and asynchronous invocations on any callable function.\u003c/p\u003e\n\n\u003cp\u003eThe features of the delegate library are:\u003c/p\u003e\n\n\u003col\u003e\n\t\u003cli\u003e\u003cstrong\u003eAny Compiler\u003c/strong\u003e \u0026ndash; standard C++ code for any compiler without weird hacks\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eAny Function\u003c/strong\u003e \u0026ndash; invoke any callable function: member, static, or free\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eAny Argument Type\u003c/strong\u003e \u0026ndash; supports any argument type: value, reference, pointer, pointer to pointer\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eMultiple Arguments\u003c/strong\u003e \u0026ndash; supports multiple function arguments\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eSynchronous Invocation\u003c/strong\u003e \u0026ndash; call the bound function synchronously\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eAsynchronous Invocation\u003c/strong\u003e \u0026ndash; call the bound function asynchronously on a client specified thread\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eBlocking Asynchronous Invocation\u003c/strong\u003e - invoke asynchronously using blocking or non-blocking delegates\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eSmart Pointer Support\u003c/strong\u003e - bind an instance function using a raw object pointer or \u003ccode\u003estd::shared_ptr\u003c/code\u003e\u003c/li\u003e\n    \u003cli\u003e\u003cstrong\u003eLambda Support\u003c/strong\u003e - bind and invoke lambda functions asynchronously using delegates.\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eAutomatic Heap Handling\u003c/strong\u003e \u0026ndash; automatically copy argument data to the heap for safe transport through a message queue\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eFixed Block Allocator\u003c/strong\u003e \u0026ndash; optionally divert heap allocation to fixed block memory pools\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eAny OS\u003c/strong\u003e \u0026ndash; easy porting to any OS. Win32 and \u003ccode\u003estd::thread\u003c/code\u003e ports included\u003c/li\u003e\n    \u003cli\u003e\u003cstrong\u003e32/64-bit\u003c/strong\u003e - Support for 32 and 64-bit projects.\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eCMake\u003c/strong\u003e - CMake supports most toolchains including Windows and Linux.\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eUnit Tests\u003c/strong\u003e - extensive unit testing of the delegate library included\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eNo External Libraries\u003c/strong\u003e \u0026ndash; delegate does not rely upon external libraries\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003eEase of Use\u003c/strong\u003e \u0026ndash; match the \u003ccode\u003eFastDelegate\u003c/code\u003e API as close as possible\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003cp\u003eThe delegate implementation significantly eases multithreaded application development by executing the delegate function with all of the function arguments on the thread of control that you specify. The framework handles all of the low-level machinery to safely invoke any function signature on a target thread.\u003c/p\u003e\n\n# Delegates Background\n\n\u003cp\u003eIf you\u0026rsquo;re not familiar with a delegate, the concept is quite simple. A delegate can be thought of as a super function pointer. In C++, there\u0026#39;s no pointer type capable of pointing to all the possible function variations: instance member, virtual, const, static, and free (global). A function pointer can\u0026rsquo;t point to instance member functions, and pointers to member functions have all sorts of limitations. However, delegate classes can, in a type-safe way, point to any function provided the function signature matches. In short, a delegate points to any function with a matching signature to support anonymous function invocation.\u003c/p\u003e\n\n\u003cp\u003eProbably the most famous C++ delegate implementation is the \u003ccode\u003eFastDelegate\u003c/code\u003e by Doug Clugston. I\u0026rsquo;ve used this code with great success on many different projects. It\u0026rsquo;s easy to use and I\u0026rsquo;ve yet to find a compiler that it doesn\u0026#39;t work on.\u003c/p\u003e\n\n\u003cp\u003eWhile the usage of \u003ccode\u003eFastDelegate\u003c/code\u003e is seamless (and fast!), examination of the code reveals numerous hacks and \u0026ldquo;horrible\u0026rdquo; casts to make it work universally across different compilers. When I first studied the source, I almost didn\u0026rsquo;t use it on a project just on looks alone because of the complexity. However, it got me to thinking; say I didn\u0026rsquo;t care so much about speed. Was it even possible to design a C++ standards compliant delegate? If so, could it match the interface and usability of \u003ccode\u003eFastDelegate\u003c/code\u003e?\u003c/p\u003e\n\n\u003cp\u003eIn practice, while a delegate is useful, a multicast version significantly expands its utility. The ability to bind more than one function pointer and sequentially invoke all registrars\u0026rsquo; makes for an effective publisher/subscriber mechanism. Publisher code exposes a delegate container and one or more anonymous subscribers register with the publisher for callback notifications.\u003c/p\u003e\n\n\u003cp\u003eThe problem with callbacks on a multithreaded system, whether it be a delegate-based or function pointer based, is that the callback occurs synchronously. Care must be taken that a callback from another thread of control is not invoked on code that isn\u0026rsquo;t thread-safe. Multithreaded application development is hard. It\u0026#39;s hard for the original designer; it\u0026#39;s hard because engineers of various skill levels must maintain the code; it\u0026#39;s hard because bugs manifest themselves in difficult ways. Ideally, an architectural solution helps to minimize errors and eases application development.\u003c/p\u003e\n\n\u003cp\u003eSome may question why \u003ccode\u003estd::function\u003c/code\u003e wasn\u0026rsquo;t used as the basis for an asynchronous delegate. Originally, I started implementing a version using \u003ccode\u003estd::function\u003c/code\u003e for targeting any callable function and it worked except for one key feature: equality. I soon discovered that you can\u0026rsquo;t compare \u003ccode\u003estd::function\u003c/code\u003e for equality which is necessary to unregister from the container. There seemed to be no easy, generic way around this. And without a means to remove previously added callable functions, the design was kaput. All is not lost. The delegate hierarchy I ultimately created actually ended up being an advantage for the feature set I was trying to accomplish. Plus it was fun to create.\u003c/p\u003e\n\n\u003cp\u003eThis C++ delegate implementation is full featured and allows calling any function, even instance member functions, with any arguments either synchronously or asynchronously. The delegate library makes binding to and invoking any function a snap.\u003c/p\u003e\n\n# Quick Start\n\nA simple publish/subscribe asynchronous delegate example.\n\n## Publisher\n\nTypically a delegate is inserted into a delegate container. \u003ccode\u003eAlarmCd\u003c/code\u003e is a delegate container. \n\n\u003cfigure\u003e\n    \u003cimg src=\"Figure1.jpg\" alt=\"Figure 1\" style=\"width:65%;\"\u003e\n    \u003cfigcaption\u003eFigure 1: AlarmCb Delegate Container\u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cp\u003e\u003c/p\u003e\n\n1. \u003ccode\u003eMulticastDelegateSafe\u003c/code\u003e - the delegate container type.\n2. \u003ccode\u003evoid(int, const string\u0026)\u003c/code\u003e - the function signature accepted by the delegate container. Any function matching can be inserted, such as a class member, static or lambda function.\n3. \u003ccode\u003eAlarmCb\u003c/code\u003e - the delegate container name. \n\n\u003cp\u003eInvoke delegate container to notify subscribers.\u003c/p\u003e\n\n```cpp\nMulticastDelegateSafe\u003cvoid(int, const string\u0026)\u003e AlarmCb;\n\nvoid NotifyAlarmSubscribers(int alarmId, const string\u0026 note)\n{\n    // Invoke delegate to generate callback(s) to subscribers\n    AlarmCb(alarmId, note);\n}\n```\n## Subscriber\n\n\u003cp\u003eTypically a subscriber registers with a delegate container instance to receive callbacks, either synchronously or asynchronously.\u003c/p\u003e\n\n\u003cfigure\u003e\n    \u003cimg src=\"Figure2.jpg\" alt=\"Figure 2\" style=\"width:75%;\"\u003e\n    \u003cfigcaption\u003eFigure 2: Insert into AlarmCb Delegate Container\u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cp\u003e\u003c/p\u003e\n\n1. \u003ccode\u003eAlarmCb\u003c/code\u003e - the publisher delegate container instance.\n2. \u003ccode\u003e+=\u003c/code\u003e - add a function target to the container. \n3. \u003ccode\u003eMakeDelegate\u003c/code\u003e - creates a delegate instance.\n4. \u003ccode\u003e\u0026alarmSub\u003c/code\u003e - the subscriber object pointer.\n5. \u003ccode\u003e\u0026AlarmSub::MemberAlarmCb\u003c/code\u003e - the subscriber callback member function.\n6. \u003ccode\u003eworkerThread1\u003c/code\u003e - the thread the callback will be invoked on. Adding a thread argument changes the callback type from synchronous to asynchronous.\n\n\u003cp\u003eCreate a function conforming to the delegate signature. Insert a callable functions into the delegate container.\u003c/p\u003e\n\n```cpp\nclass AlarmSub\n{\n    void AlarmSub()\n    {\n        // Register to receive callbacks on workerThread1\n        AlarmCb += MakeDelegate(this, \u0026AlarmSub::HandleAlarmCb, workerThread1);\n    }\n\n    void ~AlarmSub()\n    {\n        // Unregister from callbacks\n        AlarmCb -= MakeDelegate(this, \u0026AlarmSub::HandleAlarmCb, workerThread1);\n    }\n\n    void HandleAlarmCb(int alarmId, const string\u0026 note)\n    {\n        // Handle callback here. Called on workerThread1 context.\n    }\n}\n```\n\n\u003cp\u003eThis is a simple example. Many other usage patterns exist including asynchronous API's, blocking delegates with a timeout, and more.\u003c/p\u003e\n\n# Project Build\n\n\u003ca href=\"https://www.cmake.org\"\u003eCMake\u003c/a\u003e is used to create the build files. CMake is free and open-source software. Windows, Linux and other toolchains are supported. Example CMake console commands executed inside the project root directory: \n\n## Windows Visual Studio\n\n\u003ccode\u003ecmake -G \"Visual Studio 17 2022\" -A Win32 -B ../AsyncMulticastDelegateCpp11Build -S .\u003c/code\u003e\n\n\u003ccode\u003ecmake -G \"Visual Studio 17 2022\" -A x64 -B ../AsyncMulticastDelegateCpp11Build -S .\u003c/code\u003e\n\n\u003ccode\u003ecmake -G \"Visual Studio 17 2022\" -A x64 -B ../AsyncMulticastDelegateCpp11Build -S . -DENABLE_UNIT_TESTS=ON\u003c/code\u003e\n\nAfter executed, open the Visual Studio project from within the \u003ccode\u003eAsyncMulticastDelegateCpp11Build\u003c/code\u003e directory.\n\n\u003cfigure\u003e\n    \u003cimg src=\"Figure3.jpg\" alt=\"Figure 3\" style=\"width:100%;\"\u003e\n    \u003cfigcaption\u003eFigure 3: Visual Studio Build\u003c/figcaption\u003e\n\u003c/figure\u003e\n\n## Linux Make\n\n\u003ccode\u003ecmake -G \"Unix Makefiles\" -B ../AsyncMulticastDelegateCpp11Build -S .\u003c/code\u003e\n\n\u003ccode\u003ecmake -G \"Unix Makefiles\" -B ../AsyncMulticastDelegateCpp11Build -S . -DENABLE_UNIT_TESTS=ON\u003c/code\u003e\n\nAfter executed, build the software from within the AsyncMulticastDelegateCpp11Build directory using the command \u003ccode\u003emake\u003c/code\u003e. Run the console app using \u003ccode\u003e./DelegateApp\u003c/code\u003e.\n\n\u003cfigure\u003e\n    \u003cimg src=\"Figure4.jpg\" alt=\"Figure 4\" style=\"width:70%;\"\u003e\n    \u003cfigcaption\u003eFigure 4: Linux Makefile Build\u003c/figcaption\u003e\n\u003c/figure\u003e\n\n# Using the Code\n\n\u003cp\u003eI\u0026rsquo;ll first present how to use the code, and then get into the implementation details.\u003c/p\u003e\n\n\u003cp\u003eThe delegate library is comprised of delegates and delegate containers. A delegate is capable of binding to a single callable function. A multicast delegate container holds one or more delegates in a list to be invoked sequentially. A single cast delegate container holds at most one delegate.\u003c/p\u003e\n\n\u003cp\u003eThe primary delegate classes are listed below.\u003c/p\u003e\n\n\u003cul class=\"class\"\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateFree\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateFreeAsync\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateFreeAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateMember\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateMemberAsync\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateMemberAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateMemberSp\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateMemberSpAsync\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateRemoteSend\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateFreeRemoteRecv\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eDelegateMemberRemoteRecv\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003cp\u003e\u003ccode\u003eDelegateFree\u0026lt;\u0026gt;\u003c/code\u003e binds to a free or static member function. \u003ccode\u003eDelegateMember\u0026lt;\u0026gt;\u003c/code\u003e binds to a class instance member function. \u003ccode\u003eDelegateMemberSp\u0026lt;\u0026gt;\u003c/code\u003e binds to a class instance member function using a \u003ccode\u003estd::shared_ptr\u003c/code\u003e instead of a raw object pointer. All versions offer synchronous function invocation.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eDelegateFreeAsync\u0026lt;\u0026gt;\u003c/code\u003e\u003cfont color=\"#111111\" face=\"Segoe UI, Arial, sans-serif\"\u003e\u003cspan style=\"font-size: 14px\"\u003e, \u003c/span\u003e\u003c/font\u003e\u003ccode\u003eDelegateMemberAsync\u0026lt;\u0026gt;\u003c/code\u003e and \u003ccode\u003eDelegateMemberSpAsync\u0026lt;\u0026gt;\u003c/code\u003e operate in the same way as their synchronous counterparts; except these versions offer non-blocking asynchronous function execution on a specified thread of control.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eDelegateFreeAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e and \u003ccode\u003eDelegateMemberAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e provides blocking asynchronous function execution on a target thread with a caller supplied maximum wait timeout.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eDelegateRemoteSend\u0026lt;\u0026gt;\u003c/code\u003e, \u003ccode\u003eDelegateFreeRemoteRecv\u0026lt;\u0026gt;\u003c/code\u003e and \u003ccode\u003eDelegateMemberRemoteRecv\u0026gt;\u003c/code\u003e are explained in the article \u003ca href=\"https://www.codeproject.com/Articles/5262271/Remote-Procedure-Calls-using-Cplusplus-Delegates\"\u003eRemote Procedure Calls using C++ Delegates\u003c/a\u003e.\u0026nbsp;\u003c/p\u003e\n\n\u003cp\u003eThe three main delegate container classes are:\u003c/p\u003e\n\n\u003cul class=\"class\"\u003e\n\t\u003cli\u003e\u003ccode\u003eSinglecastDelegate\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eMulticastDelegate\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003e\u003ccode\u003eMulticastDelegateSafe\u0026lt;\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003cp\u003e\u003ccode\u003eSinglecastDelegate\u0026lt;\u0026gt;\u003c/code\u003e is a delegate container accepting a single delegate. The advantage of the single cast version is that it is slightly smaller and allows a return type other than \u003ccode\u003evoid\u003c/code\u003e in the bound function.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eMulticastDelegate\u0026lt;\u0026gt;\u003c/code\u003e is a delegate container implemented as a singly-linked list accepting multiple delegates. Only a delegate bound to a function with a \u003ccode\u003evoid\u003c/code\u003e return type may be added to a multicast delegate container.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eMultcastDelegateSafe\u0026lt;\u0026gt;\u003c/code\u003e is a thread-safe container implemented as a singly-linked list accepting multiple delegates. Always use the thread-safe version if multiple threads access the container instance.\u003c/p\u003e\n\n\u003cp\u003eEach container stores the delegate by value. This means the delegate is copied internally into either heap or fixed block memory depending on the mode. The user is not required to manually create a delegate on the heap before insertion into the container. Typically, the overloaded template function \u003ccode\u003eMakeDelegate()\u003c/code\u003e is used to create a delegate instance based upon the function arguments.\u003c/p\u003e\n\n## Synchronous Delegates\n\n\u003cp\u003eAll delegates are created with the overloaded \u003ccode\u003eMakeDelegate()\u003c/code\u003e template function. The compiler uses template argument deduction to select the correct \u003ccode\u003eMakeDelegate()\u003c/code\u003e version eliminating the need to manually specify the template arguments. For example, here is a simple free function.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nvoid FreeFuncInt(int value)\n{\n      cout \u0026lt;\u0026lt; \u0026quot;FreeCallback \u0026quot; \u0026lt;\u0026lt; value \u0026lt;\u0026lt; endl;\n}\u003c/pre\u003e\n\n\u003cp\u003eTo bind the free function to a delegate, create a \u003ccode\u003eDelegateFree\u0026lt;int\u0026gt;\u003c/code\u003e instance using \u003ccode\u003eMakeDelegate()\u003c/code\u003e. The \u003ccode\u003eDelegateFree\u003c/code\u003e template argument is the \u003ccode\u003eint\u003c/code\u003e function parameter. \u003ccode\u003eMakeDelegate()\u003c/code\u003e returns a \u003ccode\u003eDelegateFree\u0026lt;int\u0026gt;\u003c/code\u003e object and the following line invokes the function \u003ccode\u003eFreeFuncInt\u003c/code\u003e using the delegate.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Create a delegate bound to a free function then invoke\nDelegateFree\u0026lt;void (int)\u0026gt; delegateFree = MakeDelegate(\u0026amp;FreeFuncInt);\ndelegateFree(123);\u003c/pre\u003e\n\n\u003cp\u003eA member function is bound to a delegate in the same way. \u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Create a delegate bound to a member function then invoke\nDelegateMember\u0026lt;void (TestClass(TestStruct*))\u0026gt; delegateMember = \n                MakeDelegate(\u0026amp;testClass, \u0026amp;TestClass::MemberFunc);\ndelegateMember(\u0026amp;testStruct);\u003c/pre\u003e\n\n\u003cp\u003eRather than create a concrete free or member delegate, typically a delegate container is used to hold one or more delegates. A delegate container can hold any delegate type. For example, a multicast delegate container that binds to any function with a \u003ccode\u003evoid (int)\u003c/code\u003e function signature is shown below.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nMulticastDelegate\u0026lt;void (int)\u0026gt; delegateA;\u003c/pre\u003e\n\n\u003cp\u003eA single cast delegate is created in the same way.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nSinglecastDelegate\u0026lt;void (int)\u0026gt; delegateB;\n\u003c/pre\u003e\n\n\u003cp\u003eA function signature that returns a value, such as \u003ccode\u003efloat (int)\u003c/code\u003e, is defined by adding an additional template argument.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nSinglecastDelegate\u0026lt;float (int)\u0026gt; delegateC;\u003c/pre\u003e\n\n\u003cp\u003eA \u003ccode\u003eSinglecastDelegate\u0026lt;\u0026gt;\u003c/code\u003e may bind to a function that returns a value whereas a multicast versions cannot. The reason is that when multiple callbacks are invoked, which callback function return value should be used? The correct answer is none, so multicast containers only accept delegates with function signatures using \u003ccode\u003evoid\u003c/code\u003e as the return type.\u003c/p\u003e\n\n\u003cp\u003eMore function arguments mean using the \u003ccode\u003eMulticastDelegate\u003c/code\u003e. Currently, the library supports up to five function arguments.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nMulticastDelegate\u0026lt;void (int, int)\u0026gt; delegateD;\n\nMulticastDelegate\u0026lt;void (float, int, char)\u0026gt; delegateE;\u003c/pre\u003e\n\n\u003cp\u003eOf course, more than just built-in pass by value argument types are supported.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nMulticastDelegate\u0026lt;void (const MyClass\u0026amp;, MyStruct*, Data**)\u0026gt; delegateF;\u003c/pre\u003e\n\n\u003cp\u003eCreating a delegate instance and adding it to the multicast delegate container is accomplished with the overloaded \u003ccode\u003eMakeDelegate()\u003c/code\u003e function and \u003ccode\u003eoperator+=\u003c/code\u003e. Binding a free function or static function only requires a single function pointer argument.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ndelegateA += MakeDelegate(\u0026amp;FreeFuncInt);\u003c/pre\u003e\n\n\u003cp\u003eAn instance member function can also be added to any delegate container. For member functions, the first argument to \u003ccode\u003eMakeDelegate()\u003c/code\u003e is a pointer to the class instance. The second argument is a pointer to the member function.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ndelegateA += MakeDelegate(\u0026amp;testClass, \u0026amp;TestClass::MemberFunc);\u003c/pre\u003e\n\n\u003cp\u003eCheck for registered clients first, then invoke callbacks for all registered delegates. If multiple delegates are stored within \u003ccode\u003eMulticastDelegate\u0026lt;int\u0026gt;\u003c/code\u003e, each one is called sequentially.\u003c/p\u003e\n\n\u003cpre\u003e\n// Invoke the delegate target functions\nif (delegateA)\n      delegateA(123);\u003c/pre\u003e\n\n\u003cp\u003eRemoving a delegate instance from the delegate container uses \u003ccode\u003eoperator-=\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre\u003e\ndelegateA -= MakeDelegate(\u0026amp;FreeFuncInt);\u003c/pre\u003e\n\n\u003cp\u003eAlternatively, \u003ccode\u003eClear()\u003c/code\u003e is used to remove all delegates within the container.\u003c/p\u003e\n\n\u003cpre\u003e\ndelegateA.Clear();\u003c/pre\u003e\n\n\u003cp\u003eA delegate is added to the single cast container using \u003ccode\u003eoperator=\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nSinglecastDelegate\u0026lt;int (int)\u0026gt; delegateF;\ndelegateF = MakeDelegate(\u0026amp;FreeFuncIntRetInt);\u003c/pre\u003e\n\n\u003cp\u003eRemoval is with \u003ccode\u003eClear()\u003c/code\u003e or assigning \u003ccode\u003e0\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ndelegateF.Clear();\ndelegateF = 0;\u003c/pre\u003e\n\n## Asynchronous Non-Blocking Delegates\n\n\u003cp\u003eUp until this point, the delegates have all been synchronous. The asynchronous features are layered on top of the synchronous delegate implementation. To use asynchronous delegates, a thread-safe delegate container safely accessible by multiple threads is required. Locks protect the class API against simultaneous access. The \u0026ldquo;Safe\u0026rdquo; version is shown below.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nMulticastDelegateSafe\u0026lt;TestStruct*\u0026gt; delegateC;\u003c/pre\u003e\n\n\u003cp\u003eA thread pointer as the last argument to \u003ccode\u003eMakeDelegate()\u003c/code\u003e forces creation of an asynchronous delegate. In this case, adding a thread argument causes \u003ccode\u003eMakeDelegate()\u003c/code\u003e to return a \u003ccode\u003eDelegateMemberAsync\u0026lt;\u0026gt;\u003c/code\u003e as opposed to \u003ccode\u003eDelegateMember\u0026lt;\u0026gt;\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ndelegateC += MakeDelegate(\u0026amp;testClass, \u0026amp;TestClass::MemberFunc, workerThread1);\u003c/pre\u003e\n\n\u003cp\u003eInvocation is the same as the synchronous version, yet this time the callback function \u003ccode\u003eTestClass::MemberFunc()\u003c/code\u003e is called from \u003ccode\u003eworkerThread1\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nif (delegateC)\n      delegateC(\u0026amp;testStruct);\u003c/pre\u003e\n\n\u003cp\u003eHere is another example of an asynchronous delegate being invoked on \u003ccode\u003eworkerThread1\u003c/code\u003e with \u003ccode\u003estd::string\u003c/code\u003e and \u003ccode\u003eint\u003c/code\u003e arguments.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Create delegate with std::string and int arguments then asychronously\n// invoke on a member function\nMulticastDelegateSafe\u0026lt;void (const std::string\u0026amp;, int)\u0026gt; delegateH;\ndelegateH += MakeDelegate(\u0026amp;testClass, \u0026amp;TestClass::MemberFuncStdString, workerThread1);\ndelegateH(\u0026quot;Hello world\u0026quot;, 2016);\u003c/pre\u003e\n\n\u003cp\u003eUsage of the library is consistent between synchronous and asynchronous delegates. The only difference is the addition of a thread pointer argument to\u003ccode\u003e MakeDelegate()\u003c/code\u003e. Remember to always use the thread-safe \u003ccode\u003eMulticastDelegateSafe\u0026lt;\u0026gt;\u003c/code\u003e containers when using asynchronous delegates to callback across thread boundaries.\u003c/p\u003e\n\n\u003cp\u003eThe default behavior of the delegate library when invoking non-blocking asynchronous delegates is that arguments not passed by value are copied into heap memory for safe transport to the destination thread. This means all arguments will be duplicated. If your data is something other than plain old data (POD) and can\u0026rsquo;t be bitwise copied, then be sure to implement an appropriate copy constructor to handle the copying yourself.\u003c/p\u003e\n\n\u003cp\u003eActually there is a way to defeat the copying and really pass a pointer without copying what it\u0026rsquo;s pointing at. However, the developer must ensure that (a) the pointed to data still exists when the target thread invokes the bound function and (b) the pointed to object is thread safe. This technique is described later in the article.\u003c/p\u003e\n\n\u003cp\u003eFor more examples, see \u003cem\u003emain.cpp\u003c/em\u003e and \u003cem\u003eDelegateUnitTests.cpp\u003c/em\u003e within the attached source code.\u003c/p\u003e\n\n### Bind to std::shared_ptr\n\n\u003cp\u003eBinding to instance member function requires a pointer to an object. The delegate library supports binding with a raw pointer and a \u003ccode\u003estd::shared_ptr\u003c/code\u003e smart pointer. Usage is what you\u0026rsquo;d expect; just use a \u003ccode\u003estd::shared_ptr\u003c/code\u003e in place of the raw object pointer in the call to \u003ccode\u003eMakeDelegate()\u003c/code\u003e. Depending on if a thread argument is passed to \u003ccode\u003eMakeDelegate()\u003c/code\u003e or not, a \u003ccode\u003eDelegateMemberSp\u0026gt;\u003c/code\u003e or \u003ccode\u003eDelegateMemberSpAsync\u0026gt;\u003c/code\u003e instance is returned.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Create a shared_ptr, create a delegate, then synchronously invoke delegate function\nstd::shared_ptr\u0026lt;TestClass\u0026gt; spObject(new TestClass());\nauto delegateMemberSp = MakeDelegate(spObject, \u0026amp;TestClass::MemberFuncStdString);\ndelegateMemberSp(\u0026quot;Hello world using shared_ptr\u0026quot;, 2016);\u003c/pre\u003e\n\n\u003cp\u003eThe included VC2008 can\u0026rsquo;t use \u003ccode\u003estd::shared_ptr\u003c/code\u003e because the compiler doesn\u0026rsquo;t support the feature. Run the VS2015 project for working examples using \u003ccode\u003estd::shared_ptr\u003c/code\u003e.\u003c/p\u003e\n\n### Caution Using Raw Object Pointers\n\n\u003cp\u003eCertain asynchronous delegate usage patterns can cause a callback invocation to occur on a deleted object. The problem is this: an object function is bound to a delegate and invoked asynchronously, but before the invocation occurs on the target thread, the target object is deleted. In other words, it is possible for an object bound to a delegate to be deleted before the target thread message queue has had a chance to invoke the callback. The following code exposes the issue.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Example of a bug where the testClassHeap is deleted before the asychronous delegate \n// is invoked on the workerThread1. In other words, by the time workerThread1 calls\n// the bound delegate function the testClassHeap instance is deleted and no longer valid.\nTestClass* testClassHeap = new TestClass();\nauto delegateMemberAsync = \n    MakeDelegate(testClassHeap, \u0026amp;TestClass::MemberFuncStdString, workerThread1);\ndelegateMemberAsync(\u0026quot;Function async invoked on deleted object. Bug!\u0026quot;, 2016);\ndelegateMemberAsync.Clear();\ndelete testClassHeap;\n\u003c/pre\u003e\n\n\u003cp\u003eThe example above is contrived, but it does clearly show that nothing prevents an object being deleted while waiting for the asynchronous invocation to occur. In many embedded system architectures, the registrations might occur on singleton objects or objects that have a lifetime that spans the entire execution. In this way, the application\u0026rsquo;s usage pattern prevents callbacks into deleted objects. However, if objects pop into existence, temporarily subscribe to a delegate for callbacks, then get deleted later the possibility of a latent delegate stuck in a message queue could invoke a function on a deleted object.\u003c/p\u003e\n\n\u003cp\u003eFortunately, C++ smart pointers are just the ticket to solve these complex object lifetime issues. A \u003ccode\u003eDelegateMemberSpAsync\u0026gt;\u003c/code\u003e delegate binds using a \u003ccode\u003estd::shared_ptr\u003c/code\u003e instead of a raw object pointer. Now that the delegate has a shared pointer, the danger of the object being prematurely deleted is eliminated. The shared pointer will only delete the object pointed to once all references are no longer in use. In the code snippet below, all references to \u003ccode\u003etestClassSp\u003c/code\u003e are removed by the client code yet the delegate\u0026rsquo;s copy placed into the queue prevents \u003ccode\u003eTestClass\u003c/code\u003e deletion until after the asynchronous delegate callback occurs.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Example of the smart pointer function version of the delegate. The testClassSp instance \n// is only deleted after workerThread1 invokes the callback function thus solving the bug.\nstd::shared_ptr\u0026lt;TestClass\u0026gt; testClassSp(new TestClass());\nauto delegateMemberSpAsync = \n    MakeDelegate(testClassSp, \u0026amp;TestClass::MemberFuncStdString, workerThread1);\ndelegateMemberSpAsync(\u0026quot;Function async invoked using smart pointer. Bug solved!\u0026quot;, 2016);\ndelegateMemberSpAsync.Clear();\ntestClassSp.reset();\n\u003c/pre\u003e\n\n\u003cp\u003eActually, this technique can be used to call an object function, and then the object automatically deletes after the callback occurs. Using the above example, create a shared pointer instance, bind a delegate, and invoke the delegate. Now \u003ccode\u003etestClassSp \u003c/code\u003ecan go out of scope and \u003ccode\u003eTestClass::MemberFuncStdString\u003c/code\u003e will still be safely called on \u003ccode\u003eworkerThread1\u003c/code\u003e. The \u003ccode\u003eTestClass \u003c/code\u003einstance will delete by way of \u003ccode\u003estd::shared_ptr\u0026lt;TestClass\u0026gt;\u003c/code\u003e once the smart pointer reference count goes to \u003ccode\u003e0\u003c/code\u003e after the callback completes without any extra programmer involvement.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nstd::shared_ptr\u0026lt;TestClass\u0026gt; testClassSp(new TestClass());\nauto delegateMemberSpAsync = \n    MakeDelegate(testClassSp, \u0026amp;TestClass::MemberFuncStdString, workerThread1);\ndelegateMemberSpAsync(\u0026quot;testClassSp deletes after delegate invokes\u0026quot;, 2016);\n\u003c/pre\u003e\n\n## Asynchronous Blocking Delegates\n\n\u003cp\u003eA blocking delegate waits until the target thread executes the bound delegate function. Unlike non-blocking delegates, the blocking versions do not copy argument data onto the heap. They also allow function return types other than \u003ccode\u003evoid \u003c/code\u003ewhereas the non-blocking delegates only bind to functions returning \u003ccode\u003evoid\u003c/code\u003e. Since the function arguments are passed to the destination thread unmodified, the function executes just as you\u0026#39;d expect a synchronous version including incoming/outgoing pointers and references.\u003c/p\u003e\n\n\u003cp\u003eStack arguments passed by pointer/reference need not be thread-safe. The reason is that the calling thread blocks waiting for the destination thread to complete. This means that the delegate implementation guarantees only one thread is able to access stack allocated argument data.\u003c/p\u003e\n\n\u003cp\u003eA blocking delegate must specify a timeout in milliseconds or \u003ccode\u003eWAIT_INFINITE\u003c/code\u003e. Unlike a non-blocking asynchronous delegate, which is guaranteed to be invoked, if the timeout expires on a blocking delegate, the function is not invoked. Use \u003ccode\u003eIsSuccess()\u003c/code\u003e to determine if the delegate succeeded or not.\u003c/p\u003e\n\n\u003cp\u003eAdding a timeout as the last argument to \u003ccode\u003eMakeDelegate()\u003c/code\u003e causes a \u003ccode\u003eDelegateFreeAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e or \u003ccode\u003eDelegateMemberAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e instance to be returned depending on if a free or member function is being bound. A \u0026quot;\u003ccode\u003eWait\u003c/code\u003e\u0026quot; delegate is typically not added to a delegate container. The typical usage pattern is to create a delegate and function arguments on the stack, then invoke. The code fragment below creates a blocking delegate with the function signature \u003ccode\u003eint (std::string\u0026amp;)\u003c/code\u003e. The function is called on \u003ccode\u003eworkerThread1\u003c/code\u003e. The function \u003ccode\u003eMemberFuncStdStringRetInt()\u003c/code\u003e will update the outgoing string \u003ccode\u003emsg \u003c/code\u003eand return an integer to the caller.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nDelegateMemberAsyncWait\u0026lt;void (TestClass, std::string\u0026amp;, int)\u0026gt; delegateI =\n              MakeDelegate(\u0026amp;testClass, \u0026amp;TestClass::MemberFuncStdStringRetInt, \n                           workerThread1, WAIT_INFINITE);\nstd::string msg;\nint year = delegateI(msg);\nif (delegateI.IsSuccess())\n    cout \u0026lt;\u0026lt; msg.c_str() \u0026lt;\u0026lt; \u0026quot; \u0026quot; \u0026lt;\u0026lt; year \u0026lt;\u0026lt; endl;\u003c/pre\u003e\n\n\u003cp\u003eUsing the keyword \u003ccode\u003eauto \u003c/code\u003ewith delegates simplifies the syntax considerably.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nauto delegateI = \n    MakeDelegate(\u0026amp;testClass, \u0026amp;TestClass::MemberFuncStdStringRetInt, \n                 workerThread1, WAIT_INFINITE);\nstd::string msg;\nint year = delegateI(msg);\nif (delegateI.IsSuccess())\n    cout \u0026lt;\u0026lt; msg.c_str() \u0026lt;\u0026lt; \u0026quot; \u0026quot; \u0026lt;\u0026lt; year \u0026lt;\u0026lt; endl;\u003c/pre\u003e\n\n## Asynchronous Lambda Invocation\n\n\u003cp\u003eDelegates can invoke non-capturing\u0026nbsp;lambda functions asynchronously. The example below calls\u0026nbsp;\u003ccode\u003eLambdaFunc1\u0026nbsp;\u003c/code\u003eon\u0026nbsp;\u003ccode\u003eworkerThread1\u003c/code\u003e.\u0026nbsp;\u003c/p\u003e\n\n\u003cpre data-allowshrink=\"True\" data-codeblock-processed=\"true\" data-collapse=\"False\" id=\"pre516246\"\u003e\nauto LambdaFunc1 = +[](int i) -\u0026gt; int\n{\n    cout \u0026lt;\u0026lt; \u0026quot;Called LambdaFunc1 \u0026quot; \u0026lt;\u0026lt; i \u0026lt;\u0026lt; std::endl;\n    return ++i;\n};\n\n// Asynchronously invoke lambda on workerThread1 and wait for the return value\nauto lambdaDelegate1 = MakeDelegate(LambdaFunc1, workerThread1, WAIT_INFINITE);\nint lambdaRetVal2 = lambdaDelegate1(123);\n\u003c/pre\u003e\n\n\u003cp\u003eDelegates are callable and therefore may be passed to the standard library. The example below shows\u0026nbsp;\u003ccode\u003eCountLambda\u0026nbsp;\u003c/code\u003eexecuted asynchronously on\u0026nbsp;\u003ccode\u003eworkerThread1\u0026nbsp;\u003c/code\u003eby\u0026nbsp;\u003ccode\u003estd::count_if\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre data-allowshrink=\"True\" data-codeblock-processed=\"true\" data-collapse=\"False\" id=\"pre407028\"\u003e\nstd::vector\u0026lt;int\u0026gt; v{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };\n\nauto CountLambda = +[](int v) -\u0026gt; int\n{\n    return v \u0026gt; 2 \u0026amp;\u0026amp; v \u0026lt;= 6;\n};\nauto countLambdaDelegate = MakeDelegate(CountLambda, workerThread1, WAIT_INFINITE);\n\nconst auto valAsyncResult = std::count_if(v.begin(), v.end(),\n    countLambdaDelegate);\ncout \u0026lt;\u0026lt; \u0026quot;Asynchronous lambda result: \u0026quot; \u0026lt;\u0026lt; valAsyncResult \u0026lt;\u0026lt; endl;\u003c/pre\u003e\n\n# Delegate Library\n\n\u003cp\u003eThe delegate library contains numerous classes. A single include \u003cem\u003eDelegateLib.h\u003c/em\u003e provides access to all delegate library features. The defines within \u003cem\u003eDelegateOpt.h\u003c/em\u003e set the library options. The library is wrapped within a \u003ccode\u003eDelegateLib \u003c/code\u003enamespace. Included unit tests help ensure a robust implementation. The table below shows the delegate class hierarchy.\u003c/p\u003e\n\n```cpp\nDelegateBase\n    Delegate\u003c\u003e\n        DelegateFree\u003c\u003e\n            DelegateFreeAsync\u003c\u003e\n                DelegateFreeAsyncWait\u003c\u003e\n        DelegateMember\u003c\u003e\n            DelegateMemberAsync\u003c\u003e\n                DelegateMemberAsyncWait\u003c\u003e\n        DelegateMemberSp\u003c\u003e\n```\n\n\u003cp\u003eThroughout the following discussion, I\u0026rsquo;ll be using the one parameter version of the delegates.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eDelegateBase\u003c/code\u003e is a non-template, abstract base class common to all delegate instances. Comparison operators and a \u003ccode\u003eClone()\u003c/code\u003e method define the interface.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nclass DelegateBase {\npublic:\n      virtual ~DelegateBase() {}\n\n      /// Derived class must implement operator== to compare objects.\n      virtual bool operator==(const DelegateBase\u0026amp; rhs) const = 0;\n      virtual bool operator!=(const DelegateBase\u0026amp; rhs) { return !(*this == rhs); }\n\n\n      /// Use Clone to provide a deep copy using a base pointer. Covariant\n      /// overloading is used so that a Clone() method return type is a\n      /// more specific type in the derived class implementations.\n      /// @return A dynamic copy of this instance created with operator new.\n      /// @post The caller is responsible for deleting the clone instance.\n      virtual DelegateBase* Clone() const = 0;\n};\u003c/pre\u003e\n\n\u003cp\u003e\u003ccode\u003eDelegate\u0026lt;\u0026gt;\u003c/code\u003e provides a template class with templatized function arguments. The \u003ccode\u003eoperator()\u003c/code\u003e function allows invoking the delegate function with the correct function parameters. Covariant overloading of \u003ccode\u003eClone()\u003c/code\u003e provides a more specific return type.\u003c/p\u003e\n\n\u003cp\u003eThe \u003ccode\u003eClone()\u003c/code\u003e function is required by the delegate container classes. The delegate container needs to make copies of the delegate for storage into the list. Since the delegate container only knows about abstract base \u003ccode\u003eDelegate\u0026lt;\u0026gt;\u003c/code\u003e instances, it must use the \u003ccode\u003eClone()\u003c/code\u003e function when creating a duplicate copy.\u003c/p\u003e\n\n```cpp\n// Declare Delegate as a class template. It will be specialized for all number of arguments.\ntemplate \u003ctypename Signature\u003e\nclass Delegate;\n\n/// @brief Abstract delegate template base class.\ntemplate \u003cclass RetType\u003e\nclass Delegate\u003cRetType(void)\u003e : public DelegateBase {\npublic:\n\tvirtual RetType operator()() = 0;\n\tvirtual Delegate* Clone() const = 0;\n};\n\ntemplate \u003cclass RetType, class Param1\u003e\nclass Delegate\u003cRetType(Param1)\u003e : public DelegateBase {\npublic:\n\tvirtual RetType operator()(Param1 p1) = 0;\n\tvirtual Delegate* Clone() const = 0;\n};\n// etc...\n```\n\u003cp\u003eEfficiently storing instance member functions and free functions within the same class proves difficult. Instead, two classes were created for each type of bound function. \u003ccode\u003eDelegateMember\u0026lt;\u0026gt;\u003c/code\u003e handles instance member functions. \u003ccode\u003eDelegateFree\u0026lt;\u0026gt;\u003c/code\u003e handles free and static functions.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eDelegateMember\u0026lt;\u0026gt;\u003c/code\u003e binds to an instance member function. The addition of a \u003ccode\u003eTClass\u003c/code\u003e template argument is added above the \u003ccode\u003eParam1\u003c/code\u003e and \u003ccode\u003eRetType\u003c/code\u003e required of the inherited \u003ccode\u003eDelegate\u0026lt;\u0026gt;\u003c/code\u003e base class. \u003ccode\u003eTClass\u003c/code\u003e is required for binding to an instance member function. The delegate containers, however, cannot know about \u003ccode\u003eTClass\u003c/code\u003e. The container list may only store the most common ancestor of \u003ccode\u003eDelegateMember\u0026lt;\u0026gt;\u003c/code\u003e and \u003ccode\u003eDelegateFree\u0026lt;\u0026gt;\u003c/code\u003e, which happens to be the \u003ccode\u003eDelegate\u0026lt;\u0026gt;\u003c/code\u003e interface.\u003c/p\u003e\n\n\u003cp\u003e\u003ccode\u003eClone()\u003c/code\u003e creates a new instance of the class. \u003ccode\u003eBind()\u003c/code\u003e takes a class instance and a member function pointer. The function \u003ccode\u003eoperator()\u003c/code\u003e allows invoking the delegate function assigned with \u003ccode\u003eBind()\u003c/code\u003e.\u003c/p\u003e\n\n```cpp\n// Declare DelegateMember as a class template. It will be specialized for all number of arguments.\ntemplate \u003ctypename Signature\u003e\nclass DelegateMember;\n\n/// @brief DelegateMember is used to store and invoke an instance member function.\ntemplate \u003cclass TClass, class RetType\u003e \nclass DelegateMember\u003cRetType(TClass(void))\u003e : public Delegate\u003cRetType(void)\u003e {\npublic:\n\ttypedef TClass* ObjectPtr;\n\ttypedef RetType (TClass::*MemberFunc)(); \n\ttypedef RetType (TClass::*ConstMemberFunc)() const; \n    using ClassType = DelegateMember\u003cRetType(TClass(void))\u003e;\n\n\tDelegateMember(ObjectPtr object, MemberFunc func) { Bind(object, func); }\n\tDelegateMember(ObjectPtr object, ConstMemberFunc func) { Bind(object, func); }\n\tDelegateMember() = delete;\n\n\t/// Bind a member function to a delegate. \n\tvoid Bind(ObjectPtr object, MemberFunc func) {\n\t\tm_object = object;\n\t\tm_func = func; }\n\n\t/// Bind a const member function to a delegate. \n\tvoid Bind(ObjectPtr object, ConstMemberFunc func) {\n\t\tm_object = object;\n\t\tm_func = reinterpret_cast\u003cMemberFunc\u003e(func); }\n\n\tvirtual DelegateMember* Clone() const override { return new ClassType(*this); }\n\n\t// Invoke the bound delegate function\n\tvirtual RetType operator()() override {\n\t\tif (m_object)\n\t\t\treturn (*m_object.*m_func)();\n\t\telse\n\t\t\treturn RetType();\n\t}\n\n\tvirtual bool operator==(const DelegateBase\u0026 rhs) const override {\n\t\tauto derivedRhs = dynamic_cast\u003cconst ClassType*\u003e(\u0026rhs);\n\t\treturn derivedRhs \u0026\u0026\n\t\t\tm_func == derivedRhs-\u003em_func \u0026\u0026 \n\t\t\tm_object == derivedRhs-\u003em_object; }\n\n\tbool Empty() const { return !(m_object \u0026\u0026 m_func); }\n\tvoid Clear() { m_object = 0; m_func = 0; }\n\texplicit operator bool() const { return !Empty(); }\n\nprivate:\n\tObjectPtr m_object = nullptr;\t\t// Pointer to a class object\n\tMemberFunc m_func = nullptr;   \t\t// Pointer to an instance member function\n};\n```\n\u003cp\u003e\u003ccode\u003eDelegateFree\u0026lt;\u0026gt;\u003c/code\u003e binds to a free or static member function. Notice it inherits from \u003ccode\u003eDelegate\u0026lt;\u0026gt;\u003c/code\u003e just like \u003ccode\u003eDelegateMember\u0026lt;\u0026gt;\u003c/code\u003e. \u003ccode\u003eBind()\u003c/code\u003e takes a function pointer and \u003ccode\u003eoperator()\u003c/code\u003e allows subsequent invocation of the bound function.\u003c/p\u003e\n\n```cpp\n// Declare DelegateFree as a class template. It will be specialized for all number of arguments.\ntemplate \u003ctypename Signature\u003e\nclass DelegateFree;\n\n/// @brief DelegateFree is used to store and invoke any non-member function \n/// (i.e. a static member function or a global function). \ntemplate \u003cclass RetType\u003e \nclass DelegateFree\u003cRetType(void)\u003e : public Delegate\u003cRetType(void)\u003e {\npublic:\n\ttypedef RetType (*FreeFunc)(); \n    using ClassType = DelegateFree\u003cRetType(void)\u003e;\n\n\tDelegateFree(FreeFunc func) { Bind(func); }\n\tDelegateFree() = delete;\n\n\t/// Bind a free function to the delegate.\n\tvoid Bind(FreeFunc func) { m_func = func; }\n\n\tvirtual ClassType* Clone() const override { return new ClassType(*this); }\n\n\t/// Invoke the bound delegate function. \n\tvirtual RetType operator()() override {\n\t\tif (m_func)\n\t\t\treturn (*m_func)();\n\t\telse\n\t\t\treturn RetType();\n\t}\n\n\tvirtual bool operator==(const DelegateBase\u0026 rhs) const override {\n\t\tauto derivedRhs = dynamic_cast\u003cconst ClassType*\u003e(\u0026rhs);\n\t\treturn derivedRhs \u0026\u0026\n\t\t\tm_func == derivedRhs-\u003em_func; }\n\n\tbool Empty() const { return !m_func; }\n\tvoid Clear() { m_func = 0; }\n\texplicit operator bool() const { return !Empty(); }\n\nprivate:\n\tFreeFunc m_func = nullptr;\t\t// Pointer to a free function\n};\n\ntemplate \u003cclass RetType, class Param1\u003e \nclass DelegateFree\u003cRetType(Param1)\u003e : public Delegate\u003cRetType(Param1)\u003e {\npublic:\n\ttypedef RetType (*FreeFunc)(Param1); \n    using ClassType = DelegateFree\u003cRetType(Param1)\u003e;\n\n\tDelegateFree(FreeFunc func) { Bind(func); }\n\tDelegateFree() = delete;\n\n\t/// Bind a free function to the delegate.\n\tvoid Bind(FreeFunc func) { m_func = func; }\n\n\tvirtual ClassType* Clone() const override { return new ClassType(*this); }\n\n\t/// Invoke the bound delegate function. \n\tvirtual RetType operator()(Param1 p1) override {\n\t\tif (m_func)\n\t\t\treturn (*m_func)(p1);\n\t\telse\n\t\t\treturn RetType();\n\t}\n\n\tvirtual bool operator==(const DelegateBase\u0026 rhs) const override {\n\t\tauto derivedRhs = dynamic_cast\u003cconst ClassType*\u003e(\u0026rhs);\n\t\treturn derivedRhs \u0026\u0026\n\t\t\tm_func == derivedRhs-\u003em_func; }\n\n\tbool Empty() const { return !m_func; }\n\tvoid Clear() { m_func = 0; }\n\texplicit operator bool() const { return !Empty(); }\n\nprivate:\n\tFreeFunc m_func = nullptr;\t\t// Pointer to a free function\n};\n```\n\u003cp\u003eArguments come in different styles: by value, by reference, pointer and pointer to pointer. For non-blocking delegates, anything other than pass by value needs to have the data pointed to created on the heap to ensure the data is valid on the destination thread. The key to being able to save each parameter into \u003ccode\u003eDelegateMsg\u0026lt;\u0026gt;\u003c/code\u003e is the \u003ccode\u003eDelegateParam\u0026lt;\u0026gt;\u003c/code\u003e class as used within the \u003ccode\u003eoperator()\u003c/code\u003e function below.\u003c/p\u003e\n\n```cpp\n\t/// Invoke delegate function asynchronously\n\tvirtual void operator()(Param1 p1) override {\n\t\t// Create a new instance of the function argument data and copy\n\t\tParam1 heapParam1 = DelegateParam\u003cParam1\u003e::New(p1);\n\n\t\t// Create a clone instance of this delegate \n\t\tauto delegate = std::shared_ptr\u003cClassType\u003e(Clone());\n\n\t\t// Create a new message instance \n\t\tauto msg = std::make_shared\u003cDelegateMsg1\u003cParam1\u003e\u003e(delegate, heapParam1);\n\n\t\t// Dispatch message onto the callback destination thread. DelegateInvoke()\n\t\t// will be called by the target thread. \n\t\tm_thread.DispatchDelegate(msg);\n\n\t\tstatic_assert(!(\n\t\t\t(is_shared_ptr\u003cParam1\u003e::value \u0026\u0026 (std::is_lvalue_reference\u003cParam1\u003e::value || std::is_pointer\u003cParam1\u003e::value))),\n\t\t\t\"std::shared_ptr reference argument not allowed\");\n\t}\n```\n\n\u003cp\u003e\u003ccode\u003eDelegateMemberSpAsync\u0026lt;\u0026gt;\u003c/code\u003e is an non-blocking asychronous delegate that binds to a \u003ccode\u003estd::shared_ptr\u003c/code\u003e instead of a raw object pointer. The implementation is the same as the non-Sp version, except all locations of \u003ccode\u003eTClass*\u003c/code\u003e are replaced with \u003ccode\u003estd::shared_ptr\u0026lt;TClass\u0026gt;\u003c/code\u003e.\u003c/p\u003e\n\n```cpp\ntemplate \u003cclass TClass, class RetType, class Param1\u003e \nclass DelegateMemberSp\u003cRetType(TClass(Param1))\u003e : public Delegate\u003cRetType(Param1)\u003e {\npublic:\n\ttypedef std::shared_ptr\u003cTClass\u003e ObjectPtr;\n\ttypedef RetType (TClass::*MemberFunc)(Param1); \n\ttypedef RetType (TClass::*ConstMemberFunc)(Param1) const; \n    using ClassType = DelegateMemberSp\u003cRetType(TClass(Param1))\u003e;\n    using BaseType = Delegate\u003cRetType(Param1)\u003e;\n\n\tDelegateMemberSp(ObjectPtr object, MemberFunc func) { Bind(object, func); }\n\tDelegateMemberSp(ObjectPtr object, ConstMemberFunc func) { Bind(object, func);\t}\n\tDelegateMemberSp() = delete;\n\n\t/// Bind a member function to a delegate. \n\tvoid Bind(ObjectPtr object, MemberFunc func) {\n\t\tm_object = object;\n\t\tm_func = func; }\n\n\t/// Bind a const member function to a delegate. \n\tvoid Bind(ObjectPtr object, ConstMemberFunc func) {\n\t\tm_object = object;\n\t\tm_func = reinterpret_cast\u003cMemberFunc\u003e(func); }\n\n\tvirtual ClassType* Clone() const override { return new ClassType(*this); }\n\n\t// Invoke the bound delegate function\n    virtual RetType operator()(Param1 p1) override\n    {\n        if (m_object)\n            return (*m_object.*m_func)(p1);\n        else\n            return RetType();\n    }\n\n\tvirtual bool operator==(const DelegateBase\u0026 rhs) const override {\n\t\tauto derivedRhs = dynamic_cast\u003cconst ClassType*\u003e(\u0026rhs);\n\t\treturn derivedRhs \u0026\u0026\n\t\t\tm_func == derivedRhs-\u003em_func \u0026\u0026 \n\t\t\tm_object == derivedRhs-\u003em_object; }\n\n\tbool Empty() const { return !(m_object \u0026\u0026 m_func); }\n\tvoid Clear() { m_object = 0; m_func = 0; }\n\texplicit operator bool() const { return !Empty();  }\n\nprivate:\n\tObjectPtr m_object = nullptr;\t\t// Pointer to a class object\n\tMemberFunc m_func = nullptr;   \t// Pointer to an instance member function\n};\n```\n\u003cp\u003e\u003ccode\u003eDelegateMemberAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e is a blocking asynchronous delegate that binds to a class instance member function. \u003ccode\u003eDelegateMemberAsyncWait\u0026lt;\u0026gt;\u003c/code\u003e has a template specialization for \u003ccode\u003evoid\u003c/code\u003e return types so that functions with and without return values are supported. The two key functions are shown below. Notice that the implementation requires a semaphore to block the calling thread and a software lock to protect shared data.\u003c/p\u003e\n\n```cpp\n\t/// Invoke delegate function asynchronously\n\tvirtual RetType operator()(Param1 p1) override {\n\t\tif (m_sync)\n\t\t\treturn BaseType::operator()(p1);\n\t\telse {\n\t\t\t// Create a clone instance of this delegate \n\t\t\tauto delegate = std::shared_ptr\u003cClassType\u003e(Clone());\n\t\t\tdelegate-\u003em_sema.Create();\n\t\t\tdelegate-\u003em_sema.Reset();\n\n\t\t\t// Create a new message instance \n\t\t\tauto msg = std::make_shared\u003cDelegateMsg1\u003cParam1\u003e\u003e(delegate, p1);\n\n\t\t\t// Dispatch message onto the callback destination thread. DelegateInvoke()\n\t\t\t// will be called by the target thread. \n\t\t\tm_thread.DispatchDelegate(msg);\n\n\t\t\t// Wait for target thread to execute the delegate function\n\t\t\tif ((m_success = delegate-\u003em_sema.Wait(this-\u003em_timeout)))\n\t\t\t\tm_invoke = delegate-\u003em_invoke;\n\n\t\t\treturn m_invoke.GetRetVal();\n\t\t}\n\t}\n\n#ifdef USE_CXX17\n\t/// Invoke delegate function asynchronously\n\tauto AsyncInvoke(Param1 p1)\n\t{\n\t\tif constexpr (std::is_void\u003cRetType\u003e::value == true)\n\t\t{\n\t\t\toperator()(p1);\n\t\t\treturn IsSuccess() ? std::optional\u003cbool\u003e(true) : std::optional\u003cbool\u003e();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto retVal = operator()(p1);\n\t\t\treturn IsSuccess() ? std::optional\u003cRetType\u003e(retVal) : std::optional\u003cRetType\u003e();\n\t\t}\n\t}\n#endif\n\n\t/// Called by the target thread to invoke the delegate function \n\tvirtual void DelegateInvoke(std::shared_ptr\u003cDelegateMsgBase\u003e msg) override {\n\t\t// Typecast the base pointer to back to the templatized instance\n\t\tauto delegateMsg = std::dynamic_pointer_cast\u003cDelegateMsg1\u003cParam1\u003e\u003e(msg);\n\t\tASSERT_TRUE(delegateMsg != nullptr);\n\n\t\t// Get the function parameter data\n\t\tauto param1 = delegateMsg-\u003eGetParam1();\n\n\t\t// Invoke the delegate function then signal the waiting thread\n\t\tm_sync = true;\n\t\tm_invoke(this, param1);\n\t\tthis-\u003em_sema.Signal();\n\t}\n```\n## Argument Heap Copy\n\n\u003cp\u003eNon-blocking asynchronous invocations means that all argument data must be copied into the heap for transport to the destination thread. The \u003ccode\u003eDelegateParam\u0026lt;\u0026gt;\u003c/code\u003e class is used to \u003ccode\u003enew\u003c/code\u003e/\u003ccode\u003edelete\u003c/code\u003e arguments. Template specialization is used to define different versions of \u003ccode\u003eDelegateParam\u0026lt;\u0026gt;\u003c/code\u003e based on the argument type: pass by value, reference, pointer, pointer to pointer. The snippet below shows how it\u0026rsquo;s used to make a copy of function argument \u003ccode\u003ep1\u003c/code\u003e on the heap.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Create a new instance of the function argument data and copy\nParam1 heapParam1 = DelegateParam\u0026lt;Param1\u0026gt;::New(p1);\u003c/pre\u003e\n\n\u003cp\u003eThe actual \u003ccode\u003eNew()\u003c/code\u003e function implementation called above depends on the \u003ccode\u003eParam1\u003c/code\u003e argument type. Pass by value will call the template version shown below. It actually doesn\u0026rsquo;t create anything on the heap but instead just returns back the callers input value. The reason is that pass by value doesn\u0026rsquo;t need a heap copy as it already is a copy. \u003ccode\u003eDelete()\u003c/code\u003e therefore does nothing as there is no data to delete.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ntemplate \u0026lt;typename Param\u0026gt;\nclass DelegateParam\n{\npublic:\n      static Param New(Param param) { return param; }\n      static void Delete(Param param) { }\n};\u003c/pre\u003e\n\n\u003cp\u003eThe \u003ccode\u003eDelegateParam\u0026lt;Param *\u0026gt;\u003c/code\u003e template specialization below handles all pointer type arguments. Unlike pass by value, a pointer points at something. That something must be created on the heap so the destination thread has a full copy upon callback invocation. \u003ccode\u003eNew()\u003c/code\u003e creates the copy, and \u003ccode\u003eDelete()\u003c/code\u003e deletes it.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ntemplate \u0026lt;typename Param\u0026gt;\nclass DelegateParam\u0026lt;Param *\u0026gt;\n{\npublic:\n      static Param* New(Param* param) {\n            Param* newParam = new Param(*param);\n            return newParam;\n      }\n\n\n      static void Delete(Param* param) {\n            delete param;\n      }\n};\u003c/pre\u003e\n\n\u003cp\u003eSimilarly, there are template specializations that handle references and pointers to pointers. This way, no matter the argument type, the delegate library behaves in a consistent and correct way with no awareness or special effort on the user\u0026#39;s part.\u003c/p\u003e\n\n## Bypassing Argument Heap Copy\n\n\u003cp\u003eOccasionally, you may not want the delegate library to copy your pointer/reference arguments. Instead, you just want the destination thread to have a pointer to the original copy. Maybe the object is large or can\u0026rsquo;t be copied. Or maybe it\u0026rsquo;s a static instance that is guaranteed to exist. Either way, here is how to really send a pointer without duplicating the object pointed to.\u003c/p\u003e\n\n\u003cp\u003eThe trick is to define a \u003ccode\u003eDelegateParam\u0026lt;\u0026gt;\u003c/code\u003e template specialization to handle your specific class/struct. In the example below, the structure \u003ccode\u003eTestStructNoCopy\u003c/code\u003e will not be copied by the delegate library. The \u003ccode\u003eNew()\u003c/code\u003e function just returns the original pointer, and \u003ccode\u003eDelete()\u003c/code\u003e does nothing. Now, any \u003ccode\u003eTestStructNoCopy*\u003c/code\u003e delegate function arguments will use your \u003ccode\u003eNew()\u003c/code\u003e/\u003ccode\u003eDelete()\u003c/code\u003e and not the library\u0026rsquo;s default implementation.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ntemplate \u0026lt;\u0026gt;\nclass DelegateParam\u0026lt;TestStructNoCopy *\u0026gt;\n{\npublic:\n      static TestStructNoCopy* New(TestStructNoCopy* param) { return param; }\n      static void Delete(TestStructNoCopy* param) {}\n};\u003c/pre\u003e\n\n\u003cp\u003eUsing this technique means that the pointer you\u0026rsquo;re passing must exist when the destination thread actually invokes the callback function. In addition, if multiple threads are accessing that instance the code within the class needs to be thread-safe.\u003c/p\u003e\n\n\u003cp\u003eThis method is not required on blocking delegates, as the arguments are not copied.\u003c/p\u003e\n\n## Array Argument Heap Copy\n\n\u003cp\u003eArray function arguments are adjusted to a pointer per the C standard. In short, any function parameter declared as \u003ccode\u003eT a[]\u003c/code\u003e or \u003ccode\u003eT a[N]\u003c/code\u003e is treated as though it were declared as \u003ccode\u003eT *a\u003c/code\u003e. This means by default the delegate library \u003ccode\u003eDelegateParam\u0026lt;Param *\u0026gt;\u003c/code\u003e is called for array type parameters. Since the array size is not known, the \u003ccode\u003eDelegateParam\u0026lt;Param *\u0026gt;\u003c/code\u003e will only copy the first array element which is certainly not what is expected or desired. For instance, the function below:\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nvoid ArrayFunc(char a[]) {}\u003c/pre\u003e\n\n\u003cp\u003eRequires a delegate argument \u003ccode\u003echar*\u003c/code\u003e because the \u003ccode\u003echar a[]\u003c/code\u003e was \u0026ldquo;adjusted\u0026rdquo; to \u003ccode\u003echar *a\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nMulticastDelegateSafe\u0026lt;void (char*)\u0026gt; delegateArrayFunc;\ndelegateArrayFunc += MakeDelegate(\u0026amp;ArrayFunc, workerThread1);\u003c/pre\u003e\n\n\u003cp\u003eThere is no way to asynchronously pass a C-style array by value. The best that can be achieved is to pass the array by pointer using the previously described template specialization technique. The class below passes every \u003ccode\u003echar*\u003c/code\u003e, \u003ccode\u003echar a[]\u003c/code\u003e or \u003ccode\u003echar a[N]\u003c/code\u003e as a \u003ccode\u003echar*\u003c/code\u003e and the array pointer will be passed to the invoked function without attempting a copy. Remember, it is up to you to ensure the pointer remains valid on the destination thread.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ntemplate \u0026lt;\u0026gt;\nclass DelegateParam\u0026lt;char *\u0026gt;\n{\npublic:\n      static char* New(char* param) { return param; }\n      static void Delete(char* param) {}\n};\u003c/pre\u003e\n\n\u003cp\u003eMy recommendation is to avoid C-style arrays if possible when using asynchronous delegates to avoid confusion and mistakes.\u003c/p\u003e\n\n## Worker Thread (Win32)\n\n\u003cp\u003eAfter the \u003ccode\u003eoperator()\u003c/code\u003e function completes and the \u003ccode\u003eDelegateMsg1\u0026lt;\u0026gt;\u003c/code\u003e is put into the message queue, eventually \u003ccode\u003eWorkerThread::Process()\u003c/code\u003e will call \u003ccode\u003eDelegateInvoke()\u003c/code\u003e on the destination thread. The Win32 thread loop code below is from \u003cem\u003eWorkerThreadWin.cpp/h\u003c/em\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nunsigned long WorkerThread::Process(void* parameter)\n{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;MSG msg;\n\u0026nbsp;\u0026nbsp; \u0026nbsp;BOOL bRet;\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;// Start periodic timer\n\u0026nbsp;\u0026nbsp; \u0026nbsp;MMRESULT timerId = timeSetEvent(100, 10, \u0026amp;WorkerThread::TimerExpired, reinterpret_cast\u0026lt;DWORD\u0026gt;(this), TIME_PERIODIC);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;while ((bRet = GetMessage(\u0026amp;msg, NULL, WM_USER_BEGIN, WM_USER_END)) != 0)\n\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;switch (msg.message)\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;case WM_DISPATCH_DELEGATE:\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;ASSERT_TRUE(msg.wParam != NULL);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;// Get the ThreadMsg from the wParam value\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;ThreadMsg* threadMsg = reinterpret_cast\u0026lt;ThreadMsg*\u0026gt;(msg.wParam);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;// Convert the ThreadMsg void* data back to a DelegateMsg*\u0026nbsp;\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;DelegateMsgBase* delegateMsg = static_cast\u0026lt;DelegateMsgBase*\u0026gt;(threadMsg-\u0026gt;GetData());\u0026nbsp;\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;// Invoke the callback on the target thread\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;delegateMsg-\u0026gt;GetDelegateInvoker()-\u0026gt;DelegateInvoke(\u0026amp;delegateMsg);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;// Delete dynamic data passed through message queue\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;delete threadMsg;\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;break;\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;case WM_USER_TIMER:\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;Timer::ProcessTimers();\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;break;\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;case WM_EXIT_THREAD:\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;timeKillEvent(timerId);\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;return 0;\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;default:\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;ASSERT();\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n\u0026nbsp;\u0026nbsp; \u0026nbsp;return 0;\n}\u003c/pre\u003e\n\n\u003cp\u003eNotice the thread loop is unlike most systems that have a huge \u003ccode\u003eswitch\u003c/code\u003e statement handling various incoming data messages, type casting \u003ccode\u003evoid*\u003c/code\u003e data, then calling a specific function. The framework supports all delegate invocations with a single \u003ccode\u003eWM_DISPATCH_DELEGATE\u003c/code\u003e message. Once setup, the same small thread loop handles every delegate. New asynchronous delegates come and go as the system is designed, but the code in-between doesn\u0026#39;t change.\u003c/p\u003e\n\n\u003cp\u003eThis is a huge benefit as on many systems, getting data between threads takes a lot of manual steps. You constantly have to mess with each thread loop, create during sending, destroy data when receiving, and call various OS services and typecasts. Here, you do none of that. All the stuff in-between is neatly handled for users.\u003c/p\u003e\n\n\u003cp\u003eThe \u003ccode\u003eDelegateMemberAsync\u0026lt;\u0026gt;::DelegateInvoke()\u003c/code\u003e function calls the target function and deletes the data that traveled through the message queue.\u003c/p\u003e\n\n```cpp\n\t/// Called by the target thread to invoke the delegate function \n\tvirtual void DelegateInvoke(std::shared_ptr\u003cDelegateMsgBase\u003e msg) override {\n\t\t// Typecast the base pointer to back to the templatized instance\n\t\tauto delegateMsg = std::dynamic_pointer_cast\u003cDelegateMsg1\u003cParam1\u003e\u003e(msg);\n\t\tASSERT_TRUE(delegateMsg != nullptr);\n\n\t\t// Get the function parameter data\n\t\tauto param1 = delegateMsg-\u003eGetParam1();\n\n\t\t// Invoke the delegate function then signal the waiting thread\n\t\tm_sync = true;\n\t\tm_invoke(this, param1);\n\t\tthis-\u003em_sema.Signal();\n\t}\n```\n## Worker Thread (std::thread)\n\n\u003cp\u003eInstead of the Win32 API, an alternate implementation using the \u003ccode\u003estd::thread\u003c/code\u003e classes is included. Any C++11 compiler that supports \u003ccode\u003estd::thread\u003c/code\u003e is able to build and use the delegate library. Within \u003cem\u003eDelegateOpt.h\u003c/em\u003e, define \u003ccode\u003eUSE_STD_THREADS\u003c/code\u003e instead of \u003ccode\u003eUSE_WIN32_THREADS\u003c/code\u003e to use the \u003ccode\u003eWorkerThread\u003c/code\u003e class contained within \u003cem\u003eWorkerThreadStd.cpp/h\u003c/em\u003e. The \u003ccode\u003eLockGuard\u003c/code\u003e and \u003ccode\u003eSemaphore \u003c/code\u003eclasses are also conditionally compiled to use the C++ Standard Library instead of the Win32 API. The \u003ccode\u003estd::thread\u003c/code\u003e implemented thread loop is shown below.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nvoid WorkerThread::Process()\n{\n\u0026nbsp; \u0026nbsp; m_timerExit = false;\n\u0026nbsp; \u0026nbsp; std::thread timerThread(\u0026amp;WorkerThread::TimerThread, this);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;while (1)\n\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;std::shared_ptr\u0026lt;ThreadMsg\u0026gt; msg;\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;// Wait for a message to be added to the queue\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;std::unique_lock\u0026lt;std::mutex\u0026gt; lk(m_mutex);\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;while (m_queue.empty())\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;m_cv.wait(lk);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;if (m_queue.empty())\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;continue;\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;msg = m_queue.front();\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;m_queue.pop();\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;switch (msg-\u0026gt;GetId())\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;case MSG_DISPATCH_DELEGATE:\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;ASSERT_TRUE(msg-\u0026gt;GetData() != NULL);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;// Convert the ThreadMsg void* data back to a DelegateMsg*\u0026nbsp;\n\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; auto delegateMsg = static_cast\u0026lt;DelegateMsgBase*\u0026gt;(msg-\u0026gt;GetData());\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;// Invoke the callback on the target thread\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;delegateMsg-\u0026gt;GetDelegateInvoker()-\u0026gt;DelegateInvoke(\u0026amp;delegateMsg);\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;break;\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n\n\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; case MSG_TIMER:\n\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; Timer::ProcessTimers();\n\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; break;\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;case MSG_EXIT_THREAD:\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;{\n\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; m_timerExit = true;\n\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; timerThread.join();\n\u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; \u0026nbsp; return;\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;default:\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;ASSERT();\n\u0026nbsp;\u0026nbsp; \u0026nbsp;\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n\u0026nbsp;\u0026nbsp; \u0026nbsp;}\n}\u003c/pre\u003e\n\n# Delegate Invocation\n\n\u003cp\u003eA bound delegate function is invoked with the function \u003ccode\u003eoperator()\u003c/code\u003e. When invoking a delegate from a container, three function calls are required. One non-virtual \u003ccode\u003eoperator()\u003c/code\u003e within the delegate container, a second \u003ccode\u003evirtual\u003c/code\u003e \u003ccode\u003eoperator()\u003c/code\u003e on the delegate, then finally the bound function is called.\u003c/p\u003e\n\n\u003cp\u003eFor a multicast delegate, the container \u003ccode\u003eoperator()\u003c/code\u003e function iterates over the list calling each delegate\u0026rsquo;s \u003ccode\u003eoperator()\u003c/code\u003e. Notice, there is no return value when executing a delegate function within a multicast delegate container.\u003c/p\u003e\n\n```cpp\ntemplate\u003cclass RetType, class... Args\u003e\nclass MulticastDelegate\u003cRetType(Args...)\u003e\n{\npublic:\n    MulticastDelegate() = default;\n    ~MulticastDelegate() { Clear(); }\n\n    RetType operator()(Args... args) {\n        for (Delegate\u003cRetType(Args...)\u003e* delegate : m_delegates)\n            (*delegate)(args...);\t// Invoke delegate callback\n    }\n\n    void operator+=(const Delegate\u003cRetType(Args...)\u003e\u0026 delegate) {\n        m_delegates.push_back(delegate.Clone());\n    }\n    void operator-=(const Delegate\u003cRetType(Args...)\u003e\u0026 delegate) {\n        for (auto it = m_delegates.begin(); it != m_delegates.end(); ++it)\n        {\n            if (*((DelegateBase*)\u0026delegate) == *((DelegateBase*)(*it)))\n            {\n                delete (*it);\n                m_delegates.erase(it);\n                break;\n            }\n        }\n    }\n\n    /// Any registered delegates?\n    bool Empty() const { return m_delegates.empty(); }\n\n    /// Removal all registered delegates.\n    void Clear() {\n        auto it = m_delegates.begin();\n        while (it != m_delegates.end())\n        {\n            delete (*it);\n            it = m_delegates.erase(it);\n        }\n    }\n\n    explicit operator bool() const { return !Empty(); }\n\nprivate:\n    // Prevent copying objects\n    MulticastDelegate(const MulticastDelegate\u0026) = delete;\n    MulticastDelegate\u0026 operator=(const MulticastDelegate\u0026) = delete;\n\n    /// List of registered delegates\n    std::list\u003cDelegate\u003cRetType(Args...)\u003e*\u003e m_delegates;\n};\n```\n\u003cp\u003eFor a single cast delegate, the delegate container \u003ccode\u003eoperator()\u003c/code\u003e just calls the delegate \u003ccode\u003eoperator()\u003c/code\u003e. Notice that a return value is permitted using the single cast container.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nRetType operator()(Param p1) {\n      return (*m_delegate)(p1); } // Invoke delegate function\u003c/pre\u003e\n\n\u003cp\u003eThe containers don\u0026rsquo;t have awareness of the concrete delegate types. If the delegate stored within the container is the synchronous version, the bound function is called synchronously. When asynchronous delegates are invoked, the delegate and arguments are sent through a message queue to the destination thread.\u003c/p\u003e\n\n\u003cp\u003eWhen using a delegate without a container, the invocation is goes from the delegate \u003ccode\u003evirtual operator()\u003c/code\u003e to the bound function. The snippet below shows invoking an instance member function.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Invoke the bound delegate function\nvirtual RetType operator()(Param1 p1) const {\n      return (*m_object.*m_func)(p1); }\u003c/pre\u003e\n\n\u003cp\u003eObtaining the utmost speed from the delegate wasn\u0026rsquo;t a priority especially when you involve a message queue; a few extra instructions aren\u0026rsquo;t likely to matter much. A standard compliant delegate with the ability to derive additional functionality trumped any such optimizations.\u003c/p\u003e\n\n# Delegate Containers\n\n\u003cp\u003eDelegate containers store one or more delegates. The delegate container hierarchy is shown below:\u003c/p\u003e\n\n```cpp\nMulticastDelegate\u003c\u003e\n    MulticastDelegateSafe\u003c\u003e\nSinglecastDelegate\u003c\u003e\n```\n\u003cp\u003e\u003ccode\u003eMulticastDelegate\u0026lt;\u0026gt;\u003c/code\u003e provides the function \u003ccode\u003eoperator()\u003c/code\u003e to sequentially invoke each delegate within the list. \n\n```cpp\ntemplate\u003cclass RetType, class... Args\u003e\nclass MulticastDelegate\u003cRetType(Args...)\u003e\n{\npublic:\n    MulticastDelegate() = default;\n    ~MulticastDelegate() { Clear(); }\n\n    RetType operator()(Args... args) {\n        for (Delegate\u003cRetType(Args...)\u003e* delegate : m_delegates)\n            (*delegate)(args...);\t// Invoke delegate callback\n    }\n\n    void operator+=(const Delegate\u003cRetType(Args...)\u003e\u0026 delegate) {\n        m_delegates.push_back(delegate.Clone());\n    }\n    void operator-=(const Delegate\u003cRetType(Args...)\u003e\u0026 delegate) {\n        for (auto it = m_delegates.begin(); it != m_delegates.end(); ++it)\n        {\n            if (*((DelegateBase*)\u0026delegate) == *((DelegateBase*)(*it)))\n            {\n                delete (*it);\n                m_delegates.erase(it);\n                break;\n            }\n        }\n    }\n\n    /// Any registered delegates?\n    bool Empty() const { return m_delegates.empty(); }\n\n    /// Removal all registered delegates.\n    void Clear() {\n        auto it = m_delegates.begin();\n        while (it != m_delegates.end())\n        {\n            delete (*it);\n            it = m_delegates.erase(it);\n        }\n    }\n\n    explicit operator bool() const { return !Empty(); }\n\nprivate:\n    // Prevent copying objects\n    MulticastDelegate(const MulticastDelegate\u0026) = delete;\n    MulticastDelegate\u0026 operator=(const MulticastDelegate\u0026) = delete;\n\n    /// List of registered delegates\n    std::list\u003cDelegate\u003cRetType(Args...)\u003e*\u003e m_delegates;\n};\n```\n# Examples\n\n## SysData Example\n\n\u003cp\u003eA few real-world examples will demonstrate common delegate usage patterns. First, \u003ccode\u003eSysData\u003c/code\u003e is a simple class showing how to expose an outgoing asynchronous interface. The class stores system data and provides asynchronous subscriber notifications when the mode changes. The class interface is shown below.\u003c/p\u003e\n\n```cpp\nclass SysData\n{\npublic:\n\t/// Clients register with MulticastDelegateSafe to get callbacks when system mode changes\n\tMulticastDelegateSafe\u003cvoid(const SystemModeChanged\u0026)\u003e SystemModeChangedDelegate;\n\n\t/// Get singleton instance of this class\n\tstatic SysData\u0026 GetInstance();\n\n\t/// Sets the system mode and notify registered clients via SystemModeChangedDelegate.\n\t/// @param[in] systemMode - the new system mode. \n\tvoid SetSystemMode(SystemMode::Type systemMode);\t\n\nprivate:\n\tSysData();\n\t~SysData();\n\n\t/// The current system mode data\n\tSystemMode::Type m_systemMode;\n\n\t/// Lock to make the class thread-safe\n\tLOCK m_lock;\n};\n```\n\u003cp\u003eThe subscriber interface for receiving callbacks is \u003ccode\u003eSystemModeChangedDelegate\u003c/code\u003e. Calling \u003ccode\u003eSetSystemMode()\u003c/code\u003e saves the new mode into \u003ccode\u003em_systemMode\u003c/code\u003e and notifies all registered subscribers.\u003c/p\u003e\n\n```cpp\nvoid SysData::SetSystemMode(SystemMode::Type systemMode)\n{\n\tLockGuard lockGuard(\u0026m_lock);\n\n\t// Create the callback data\n\tSystemModeChanged callbackData;\n\tcallbackData.PreviousSystemMode = m_systemMode;\n\tcallbackData.CurrentSystemMode = systemMode;\n\n\t// Update the system mode\n\tm_systemMode = systemMode;\n\n\t// Callback all registered subscribers\n\tif (SystemModeChangedDelegate)\n\t\tSystemModeChangedDelegate(callbackData);\n}\n```\n## SysDataClient Example\n\n\u003cp\u003e\u003ccode\u003eSysDataClient\u003c/code\u003e is a delegate subscriber and registers for \u003ccode\u003eSysData::SystemModeChangedDelegate\u003c/code\u003e notifications within the constructor.\u003c/p\u003e\n\n```cpp\nclass SysDataClient\n{\npublic:\n\t// Constructor\n\tSysDataClient() :\n\t\tm_numberOfCallbacks(0)\n\t{\n\t\t// Register for async delegate callbacks\n\t\tSysData::GetInstance().SystemModeChangedDelegate += MakeDelegate(this, \u0026SysDataClient::CallbackFunction, workerThread1);\n\t\tSysDataNoLock::GetInstance().SystemModeChangedDelegate += MakeDelegate(this, \u0026SysDataClient::CallbackFunction, workerThread1);\n\t}\n\n\t~SysDataClient()\n\t{\n\t\t// Unregister the all registered delegates at once\n\t\tSysData::GetInstance().SystemModeChangedDelegate.Clear(); \n\n\t\t// Alternatively unregister a single delegate\n\t\tSysDataNoLock::GetInstance().SystemModeChangedDelegate -= MakeDelegate(this, \u0026SysDataClient::CallbackFunction, workerThread1);\n\t}\n\nprivate:\n\tvoid CallbackFunction(const SystemModeChanged\u0026 data)\n\t{\n\t\tm_numberOfCallbacks++;\n\t\tcout \u003c\u003c \"CallbackFunction \" \u003c\u003c data.CurrentSystemMode \u003c\u003c endl;\n\t}\n\n\tint m_numberOfCallbacks;\n};\n```\n\u003cp\u003e\u003ccode\u003eSysDataClient::CallbackFunction()\u003c/code\u003e is now called on \u003ccode\u003eworkerThread1 \u003c/code\u003ewhen the system mode changes.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nvoid CallbackFunction(const SystemModeChanged\u0026amp; data)\n{\n    m_numberOfCallbacks++;\n    cout \u0026lt;\u0026lt; \u0026quot;CallbackFunction \u0026quot; \u0026lt;\u0026lt; data.CurrentSystemMode \u0026lt;\u0026lt; endl;\n}\u003c/pre\u003e\n\n\u003cp\u003eWhen \u003ccode\u003eSetSystemMode()\u003c/code\u003e is called, anyone interested in the mode changes are notified synchronously or asynchronously depending on the delegate type registered.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\n// Set new SystemMode values. Each call will invoke callbacks to all\n// registered client subscribers.\nSysData::GetInstance().SetSystemMode(SystemMode::STARTING);\nSysData::GetInstance().SetSystemMode(SystemMode::NORMAL);\u003c/pre\u003e\n\n## SysDataNoLock Example\n\n\u003cp\u003e\u003ccode\u003eSysDataNoLock\u003c/code\u003e is an alternate implementation that uses a \u003ccode\u003eprivate\u003c/code\u003e \u003ccode\u003eMulticastDelegateSafe\u0026lt;\u0026gt;\u003c/code\u003e for setting the system mode asynchronously and without locks.\u003c/p\u003e\n\n```cpp\nclass SysDataNoLock\n{\npublic:\n\t/// Clients register with MulticastDelegateSafe1 to get callbacks when system mode changes\n\tMulticastDelegateSafe\u003cvoid(const SystemModeChanged\u0026)\u003e SystemModeChangedDelegate;\n\n\t/// Get singleton instance of this class\n\tstatic SysDataNoLock\u0026 GetInstance();\n\n\t/// Sets the system mode and notify registered clients via SystemModeChangedDelegate.\n\t/// @param[in] systemMode - the new system mode. \n\tvoid SetSystemMode(SystemMode::Type systemMode);\t\n\n\t/// Sets the system mode and notify registered clients via a temporary stack created\n\t/// asynchronous delegate. \n\t/// @param[in] systemMode - The new system mode. \n\tvoid SetSystemModeAsyncAPI(SystemMode::Type systemMode);\t\n\n\t/// Sets the system mode and notify registered clients via a temporary stack created\n\t/// asynchronous delegate. This version blocks (waits) until the delegate callback\n\t/// is invoked and returns the previous system mode value. \n\t/// @param[in] systemMode - The new system mode. \n\t/// @return The previous system mode. \n\tSystemMode::Type SetSystemModeAsyncWaitAPI(SystemMode::Type systemMode);\n\nprivate:\n\tSysDataNoLock();\n\t~SysDataNoLock();\n\n\t/// Private callback to get the SetSystemMode call onto a common thread\n\tMulticastDelegateSafe\u003cvoid (SystemMode::Type)\u003e SetSystemModeDelegate;\n\n\t/// Sets the system mode and notify registered clients via SystemModeChangedDelegate.\n\t/// @param[in] systemMode - the new system mode. \n\tvoid SetSystemModePrivate(SystemMode::Type);\t\n\n\t/// The current system mode data\n\tSystemMode::Type m_systemMode;\n};\n\n```\n\n\u003cp\u003eThe constructor registers \u003ccode\u003eSetSystemModePrivate()\u003c/code\u003e with the private \u003ccode\u003eSetSystemModeDelegate\u003c/code\u003e.\u003c/p\u003e\n\n```cpp\nSysDataNoLock::SysDataNoLock() :\n\tm_systemMode(SystemMode::STARTING)\n{\n\tSetSystemModeDelegate += MakeDelegate(this, \u0026SysDataNoLock::SetSystemModePrivate, workerThread2);\n\tworkerThread2.CreateThread();\n}\n```\n\u003cp\u003eThe \u003ccode\u003eSetSystemMode()\u003c/code\u003e function below is an example of an asynchronous incoming interface. To the caller, it looks like a normal function, but under the hood, a private member call is invoked asynchronously using a delegate. In this case, invoking \u003ccode\u003eSetSystemModeDelegate\u003c/code\u003e causes \u003ccode\u003eSetSystemModePrivate()\u003c/code\u003e to be called on \u003ccode\u003eworkerThread2\u003c/code\u003e.\u003c/p\u003e\n\n```cpp\nvoid SysDataNoLock::SetSystemMode(SystemMode::Type systemMode)\n{\n\t// Invoke the private callback. SetSystemModePrivate() will be called on workerThread2.\n\tSetSystemModeDelegate(systemMode);\n}\n```\n\u003cp\u003eSince this private function is always invoked asynchronously on \u003ccode\u003eworkerThread2\u003c/code\u003e, it doesn\u0026#39;t require locks.\u003c/p\u003e\n\n```cpp\nvoid SysDataNoLock::SetSystemModePrivate(SystemMode::Type systemMode)\n{\n\t// Create the callback data\n\tSystemModeChanged callbackData;\n\tcallbackData.PreviousSystemMode = m_systemMode;\n\tcallbackData.CurrentSystemMode = systemMode;\n\n\t// Update the system mode\n\tm_systemMode = systemMode;\n\n\t// Callback all registered subscribers\n\tif (SystemModeChangedDelegate)\n\t\tSystemModeChangedDelegate(callbackData);\n}\n```\n## SysDataNoLock Reinvoke Example\n\n\u003cp\u003eWhile creating a separate private function to create an asynchronous API does work, with delegates, it\u0026#39;s possible to just reinvoke the same exact function just on a different thread. Perform a simple check whether the caller is executing on the desired thread of control. If not, a temporary asynchronous delegate is created on the stack and then invoked. The delegate and all the caller\u0026rsquo;s original function arguments are duplicated on the heap and the function is reinvoked on \u003ccode\u003eworkerThread2\u003c/code\u003e. This is an elegant way to create asynchronous APIs with the absolute minimum of effort.\u003c/p\u003e\n\n```cpp\nvoid SysDataNoLock::SetSystemModeAsyncAPI(SystemMode::Type systemMode)\n{\n\t// Is the caller executing on workerThread2?\n\tif (workerThread2.GetThreadId() != WorkerThread::GetCurrentThreadId())\n\t{\n\t\t// Create an asynchronous delegate and re-invoke the function call on workerThread2\n\t\tDelegateMemberAsync\u003cvoid (SysDataNoLock(SystemMode::Type))\u003e delegate = MakeDelegate(this, \u0026SysDataNoLock::SetSystemModeAsyncAPI, workerThread2);\n\t\tdelegate(systemMode);\n\t\treturn;\n\t}\n\n\t// Create the callback data\n\tSystemModeChanged callbackData;\n\tcallbackData.PreviousSystemMode = m_systemMode;\n\tcallbackData.CurrentSystemMode = systemMode;\n\n\t// Update the system mode\n\tm_systemMode = systemMode;\n\n\t// Callback all registered subscribers\n\tif (SystemModeChangedDelegate)\n\t\tSystemModeChangedDelegate(callbackData);\n}\n```\n## SysDataNoLock Blocking Reinvoke Example\n\n\u003cp\u003eA blocking asynchronous API can be hidden inside a class member function. The function below sets the current mode on \u003ccode\u003eworkerThread2\u003c/code\u003e and returns the previous mode. A blocking delegate is created on the stack and invoked if the caller isn\u0026#39;t executing on \u003ccode\u003eworkerThread2\u003c/code\u003e. To the caller, the function appears synchronous, but the delegate ensures that the call is executed on the proper thread before returning.\u003c/p\u003e\n\n```cpp\nSystemMode::Type SysDataNoLock::SetSystemModeAsyncWaitAPI(SystemMode::Type systemMode)\n{\n\t// Is the caller executing on workerThread2?\n\tif (workerThread2.GetThreadId() != WorkerThread::GetCurrentThreadId())\n\t{\n\t\t// Create an asynchronous delegate and re-invoke the function call on workerThread2\n\t\tDelegateMemberAsyncWait\u003cSystemMode::Type (SysDataNoLock(SystemMode::Type))\u003e delegate =\n\t\t\tMakeDelegate(this, \u0026SysDataNoLock::SetSystemModeAsyncWaitAPI, workerThread2, WAIT_INFINITE);\n\t\treturn delegate(systemMode);\n\t}\n\n\t// Create the callback data\n\tSystemModeChanged callbackData;\n\tcallbackData.PreviousSystemMode = m_systemMode;\n\tcallbackData.CurrentSystemMode = systemMode;\n\n\t// Update the system mode\n\tm_systemMode = systemMode;\n\n\t// Callback all registered subscribers\n\tif (SystemModeChangedDelegate)\n\t\tSystemModeChangedDelegate(callbackData);\n\n\treturn callbackData.PreviousSystemMode;\n}\n```\n## Timer Example\n\n\u003cp\u003eOnce a delegate framework is in place, creating a timer callback service is trivial. Many systems need a way to generate a callback based on a timeout. Maybe it\u0026#39;s a periodic timeout for some low speed polling or maybe an error timeout in case something doesn\u0026#39;t occur within the expected time frame. Either way, the callback must occur on a specified thread of control. A \u003ccode\u003eSinglecastDelegate0\u0026lt;\u0026gt;\u003c/code\u003e used inside a \u003ccode\u003eTimer\u003c/code\u003e class solves this nicely.\u003c/p\u003e\n\n```cpp\nclass Timer \n{\npublic:\n\t/// Client's register with Expired to get timer callbacks\n\tSinglecastDelegate\u003cvoid(void)\u003e Expired;\n\n\t/// Constructor\n\tTimer(void);\n\n\t/// Destructor\n\t~Timer(void);\n\n\t/// Starts a timer for callbacks on the specified timeout interval.\n\t/// @param[in]\ttimeout - the timeout in milliseconds.\n\tvoid Start(unsigned long timeout);\n\n\t/// Stops a timer.\n\tvoid Stop();\n\n    //...\n```\n\n\u003cp\u003eUsers create an instance of the timer and register for the expiration. In this case, \u003ccode\u003eMyClass::MyCallback()\u003c/code\u003e is called in 250ms.\u003c/p\u003e\n\n```cpp\n    Timer timer;\n    timer.Expired = MakeDelegate(\u0026TimerExpiredCb, workerThread1);\n    timer.Start(250);\n```\n\n# Heap vs. Fixed Block\n\n\u003cp\u003eThe heap is used to create duplicate copies of the delegate and function arguments. When adding a delegate to a multicast list, it is cloned using operator \u003ccode\u003enew\u003c/code\u003e. The asynchronous delegate support requires copying the delegate and all arguments for placement into a message queue. Normally, the memory comes from the heap. On many systems, this is not a problem. However, some system can\u0026rsquo;t use the heap in an uncontrolled fashion due to the possibility of a heap fragmentation memory fault. This occurs when the heap memory gets chopped up into small blocks over long executions such that a memory request fails.\u003c/p\u003e\n\n\u003cp\u003eA fixed block memory allocator is included within the source files. Just uncomment the \u003ccode\u003eUSE_XALLOCATOR\u003c/code\u003e define within \u003cem\u003eDelegateOpt.h\u003c/em\u003e to enable using the fixed allocator. When enabled, all dynamic memory requests originating from the \u003ccode\u003edelegate\u003c/code\u003e library are routed to the fixed block allocators. The \u003ccode\u003exallocator\u003c/code\u003e also has the advantage of faster execution than the heap thus limiting the speed impact of dynamic memory allocation.\u003c/p\u003e\n\n\u003cp\u003eThe entire \u003ccode\u003edelegate\u003c/code\u003e hierarchy is routed to fixed block usage with a single \u003ccode\u003eXALLOCATOR\u003c/code\u003e macro inside \u003ccode\u003eDelegateBase\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nclass DelegateBase {\n#if USE_XALLOCATOR\n      XALLOCATOR\n#endif\u003c/pre\u003e\n\n\u003cp\u003eThe \u003ccode\u003edelegate\u003c/code\u003e library copies function arguments when necessary for asynchronous support. The memory requests are routed to the fixed block allocator by way of the \u003ccode\u003eDelegateParam\u0026lt;\u0026gt;\u003c/code\u003e class. Notice that if \u003ccode\u003eUSE_ALLOCATOR\u003c/code\u003e is defined, the memory is obtained within \u003ccode\u003eNew()\u003c/code\u003e is from \u003ccode\u003exmalloc()\u003c/code\u003e and the placement \u003ccode\u003enew\u003c/code\u003e syntax is used to construct the object within the fixed block region. Inside \u003ccode\u003eDelete()\u003c/code\u003e, the destructor is called manually then \u003ccode\u003exfree()\u003c/code\u003e is used to return the fixed block memory.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\ntemplate \u0026lt;typename Param\u0026gt;\nclass DelegateParam\u0026lt;Param *\u0026gt;\n{\npublic:\n      static Param* New(Param* param) {\n#if USE_XALLOCATOR\n            void* mem = xmalloc(sizeof(*param));\n            Param* newParam = new (mem) Param(*param);\n#else\n            Param* newParam = new Param(*param);\n#endif\n            return newParam;\n      }\n\n      static void Delete(Param* param) {\n#if USE_XALLOCATOR\n            param-\u0026gt;~Param();\n            xfree((void*)param);\n#else\n            delete param;\n#endif\n      }\n};\u003c/pre\u003e\n\n\u003cp\u003eSee the article \u0026ldquo;\u003ca href=\"https://www.codeproject.com/Articles/1084801/Replace-malloc-free-with-a-Fast-Fixed-Block-Memory\"\u003e\u003cstrong\u003eReplace malloc/free with a Fast Fixed Block Memory Allocator\u003c/strong\u003e\u003c/a\u003e\u0026rdquo; for more information.\u003c/p\u003e\n\n# Porting\n\n\u003cp\u003eThe code is an easy port to any platform. There are only three OS services required: threads, a semaphore and a software lock. The code is separated into five directories.\u003c/p\u003e\n\n\u003col\u003e\n\t\u003cli\u003e\u003cem\u003e\u003cstrong\u003eDelegate\u003c/strong\u003e\u003c/em\u003e - core delegate library implementation files\u003c/li\u003e\n\t\u003cli\u003e\u003cem\u003e\u003cstrong\u003ePort\u003c/strong\u003e\u003c/em\u003e \u0026ndash; thread-specific files\u003c/li\u003e\n\t\u003cli\u003e\u003cem\u003e\u003cstrong\u003eExamples\u003c/strong\u003e\u003c/em\u003e \u0026ndash; sample code showing usage\u003c/li\u003e\n\t\u003cli\u003e\u003cem\u003e\u003cstrong\u003eVS2008\u003c/strong\u003e\u003c/em\u003e \u0026ndash; Visual Studio 2008 project files\u003c/li\u003e\n\t\u003cli\u003e\u003cem\u003e\u003cstrong\u003eVS2015\u003c/strong\u003e\u003c/em\u003e \u0026ndash; Visual Studio 2015 project files\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003cp\u003eThe Eclipse project files are located at the project root (\u003cem\u003e.cproject\u003c/em\u003e and \u003cem\u003e.project\u003c/em\u003e). Use the \u003cstrong\u003eFile\u003c/strong\u003e \u0026gt; \u003cstrong\u003eImport...\u003c/strong\u003e \u0026gt; \u003cstrong\u003eGeneral\u003c/strong\u003e \u0026gt; \u003cstrong\u003eExisting Projects into Workspace\u003c/strong\u003e option to add the project to your workspace.\u003c/p\u003e\n\n\u003cp\u003eThe library has a single \u003ccode\u003eabstract\u003c/code\u003e class \u003ccode\u003eDelegateThread\u003c/code\u003e with a single pure \u003ccode\u003evirtual\u003c/code\u003e function that needs to be implemented on each target OS.\u003c/p\u003e\n\n\u003cpre\u003e\nvirtual void DispatchDelegate(DelegateMsgBase* msg) = 0;\u003c/pre\u003e\n\n\u003cp\u003eOn most projects, I wrap the underlying raw OS calls into a thread class to encapsulate and enforce the correct behavior. Here, I provide \u003ccode\u003eThreadWin\u003c/code\u003e class as a wrapper over the \u003ccode\u003eCreateThread()\u003c/code\u003e Windows API.\u003c/p\u003e\n\n\u003cp\u003eOnce you have a thread class, just inherit the \u003ccode\u003eDelegateThread\u003c/code\u003e interface and implement the \u003ccode\u003eDispatchDelegate()\u003c/code\u003e function. Using the Win32 API, a simple post to a message queue is all that is required:\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nvoid ThreadWin::DispatchDelegate(DelegateMsgBase* msg)\n{\n      // Create a new ThreadMsg\n      ThreadMsg* threadMsg = new ThreadMsg(WM_DISPATCH_DELEGATE, msg);\n\n      // Post the message to the this thread\u0026#39;s message queue\n      PostThreadMessage(WM_DISPATCH_DELEGATE, threadMsg);\n}\u003c/pre\u003e\n\n\u003cp\u003eThe alternate implementation using the C++ Standard Library adds the message to a \u003ccode\u003estd::queue\u003c/code\u003e protected by a mutex.\u003c/p\u003e\n\n\u003cpre\u003e\nvoid WorkerThread::DispatchDelegate(DelegateLib::DelegateMsgBase* msg)\n{\n\u0026nbsp;\u0026nbsp; \u0026nbsp;ASSERT_TRUE(m_thread);\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;// Create a new ThreadMsg\n\u0026nbsp; \u0026nbsp; std::shared_ptr\u0026lt;ThreadMsg\u0026gt; threadMsg(new ThreadMsg(MSG_DISPATCH_DELEGATE, msg));\n\n\u0026nbsp;\u0026nbsp; \u0026nbsp;// Add dispatch delegate msg to queue and notify worker thread\n\u0026nbsp;\u0026nbsp; \u0026nbsp;std::unique_lock\u0026lt;std::mutex\u0026gt; lk(m_mutex);\n\u0026nbsp;\u0026nbsp; \u0026nbsp;m_queue.push(threadMsg);\n\u0026nbsp;\u0026nbsp; \u0026nbsp;m_cv.notify_one();\n}\u003c/pre\u003e\n\n\u003cp\u003eSoftware locks are handled by the \u003ccode\u003eLockGuard\u003c/code\u003e class. This class can be updated with locks of your choice, or you can use a different mechanism. Locks are only used in a few places. The \u003ccode\u003eSemaphore\u003c/code\u003e class wraps the Windows event objects or \u003ccode\u003estd::mutex\u003c/code\u003e required by the blocking delegate implementation.\u003c/p\u003e\n\n\u003cp\u003eIn short, the library supports Win32 and \u003ccode\u003estd::thread\u003c/code\u003e models by defining \u003ccode\u003eUSE_WIN32_THREADS\u003c/code\u003e or \u003ccode\u003eUSE_STD_THREADS\u003c/code\u003e within \u003cem\u003eDelegateOpt.h\u003c/em\u003e. If your C++11 or higher compiler supports \u003ccode\u003estd::thread\u003c/code\u003e, then you\u0026#39;re good to go. For other OSs, just provide an implementation for \u003ccode\u003eDelegateThread::DispatchDelegate()\u003c/code\u003e, update the \u003ccode\u003eLockGuard\u003c/code\u003e and \u003ccode\u003eSemaphore\u003c/code\u003e classes, and put a small amount of code in your thread loop to call \u003ccode\u003eDelegateInvoke()\u003c/code\u003e and the \u003ccode\u003edelegate\u003c/code\u003e library can be deployed on any platform.\u003c/p\u003e\n\n# Summary\n\n\u003cp\u003eAll delegates can be created with \u003ccode\u003eMakeDelegate()\u003c/code\u003e. The function arguments determine the delegate type returned.\u003c/p\u003e\n\n\u003cp\u003eSynchronous delegates are created using one argument for free functions and two for instance member functions.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nauto freeDelegate = MakeDelegate(\u0026amp;MyFreeFunc);\nauto memberDelegate = MakeDelegate(\u0026amp;myClass, \u0026amp;MyClass::MyMemberFunc);\u003c/pre\u003e\n\n\u003cp\u003eAdding the thread argument creates a non-blocking asynchronous delegate.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nauto freeDelegate = MakeDelegate(\u0026amp;MyFreeFunc, myThread);\nauto memberDelegate = MakeDelegate(\u0026amp;myClass, \u0026amp;MyClass::MyMemberFunc, myThread);\u003c/pre\u003e\n\n\u003cp\u003eIf using C++11, a \u003ccode\u003estd::shared_ptr\u003c/code\u003e can replace a raw instance pointer on synchronous and non-blocking asynchronous member delegates.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nstd::shared_ptr\u0026lt;MyClass\u0026gt; myClass(new MyClass());\nauto memberDelegate = MakeDelegate(myClass, \u0026amp;MyClass::MyMemberFunc, myThread);\u003c/pre\u003e\n\n\u003cp\u003eAdding a timeout argument creates a blocking asynchronous delegate.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nauto freeDelegate = MakeDelegate(\u0026amp;MyFreeFunc, myThread, WAIT_INFINITE);\nauto memberDelegate = MakeDelegate(\u0026amp;myClass, \u0026amp;MyClass::MyMemberFunc, myThread, 5000);\u003c/pre\u003e\n\n\u003cp\u003eDelegates are added/removed from multicast containers using \u003ccode\u003eoperator+=\u003c/code\u003e and \u003ccode\u003eoperator-=\u003c/code\u003e. All containers accept all delegate types.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nMulticastDelegate\u0026lt;void (int)\u0026gt; multicastContainer;\nmulticastContainer += MakeDelegate(\u0026amp;MyFreeFunc);\nmulticastContainer -= MakeDelegate(\u0026amp;MyFreeFunc);\u003c/pre\u003e\n\n\u003cp\u003eUse the thread-safe multicast delegate container when using asynchronous delegates to allow multiple threads to safely add/remove from the container.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nMulticastDelegateSafe\u0026lt;void (int)\u0026gt; multicastContainer;\nmulticastContainer += MakeDelegate(\u0026amp;MyFreeFunc, myThread);\nmulticastContainer -= MakeDelegate(\u0026amp;MyFreeFunc, myThread);\u003c/pre\u003e\n\n\u003cp\u003eSingle cast delegates are added and removed using \u003ccode\u003eoperator=\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nSinglecastDelegate\u0026lt;void (int)\u0026gt; singlecastContainer;\nsinglecastContainer = MakeDelegate(\u0026amp;MyFreeFunc);\nsinglecastContainer = 0;\u003c/pre\u003e\n\n\u003cp\u003eAll delegates and delegate containers are invoked using \u003ccode\u003eoperator()\u003c/code\u003e.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nif (myDelegate)\n      myDelegate(123);\u003c/pre\u003e\n\n\u003cp\u003eUse \u003ccode\u003eIsSuccess()\u003c/code\u003e on blocking delegates before using the return value or outgoing arguments.\u003c/p\u003e\n\n\u003cpre lang=\"C++\"\u003e\nif (myDelegate) {\n     int outInt = 0;\n     int retVal = myDelegate(\u0026amp;outInt);\n     if (myDelegate.IsSuccess()) {\n            cout \u0026lt;\u0026lt; outInt \u0026lt;\u0026lt; retVal;\n     }        \n}\u003c/pre\u003e\n\n# \u003ca name=\"whichcallback\"\u003eWhich Callback Implementation?\u003c/a\u003e\n\n\u003cp\u003eI\u0026rsquo;ve documented four different asynchronous multicast callback implementations here on CodeProject. Each version has its own unique features and advantages. The sections below highlight the main differences between each solution. See the \u003cstrong\u003eReferences \u003c/strong\u003esection below for links to each article.\u003c/p\u003e\n\n\u003cp\u003eThis asynchronous delegate implementation strives to ease inter-thread communication by invoking functions and passing data between threads using C++ delegates. Remote delegates extend the library to include inter-process and inter-processor communications.\u0026nbsp;See the \u003cstrong\u003eReferences \u003c/strong\u003esection below for a the explaination of the remote procedure call using C++ delegates implementation.\u003c/p\u003e\n\n## Asynchronous Multicast Callbacks in C\n\n\u003cul\u003e\n\t\u003cli\u003eImplemented in C\u003c/li\u003e\n\t\u003cli\u003eCallback function is a free or static member only\u003c/li\u003e\n\t\u003cli\u003eOne callback argument supported\u003c/li\u003e\n\t\u003cli\u003eCallback argument must be a pointer type\u003c/li\u003e\n\t\u003cli\u003eCallback argument data copied with \u003ccode\u003ememcpy\u003c/code\u003e\u003c/li\u003e\n\t\u003cli\u003eType-safety provided by macros\u003c/li\u003e\n\t\u003cli\u003eStatic array holds registered subscriber callbacks\u003c/li\u003e\n\t\u003cli\u003eNumber of registered subscribers fixed at compile time\u003c/li\u003e\n\t\u003cli\u003eFixed block memory allocator in C\u003c/li\u003e\n\t\u003cli\u003eCompact implementation\u003c/li\u003e\n\u003c/ul\u003e\n\n## Asynchronous Multicast Callbacks with Inter-Thread Messaging\n\n\u003cul\u003e\n\t\u003cli\u003eImplemented in C++\u003c/li\u003e\n\t\u003cli\u003eCallback function is a free or static member only\u003c/li\u003e\n\t\u003cli\u003eOne callback argument supported\u003c/li\u003e\n\t\u003cli\u003eCallback argument must be a pointer type\u003c/li\u003e\n\t\u003cli\u003eCallback argument data copied with copy constructor\u003c/li\u003e\n\t\u003cli\u003eType-safety provided by templates\u003c/li\u003e\n\t\u003cli\u003eMinimal use of templates\u003c/li\u003e\n\t\u003cli\u003eDynamic list of registered subscriber callbacks\u003c/li\u003e\n\t\u003cli\u003eNumber of registered subscribers expands at runtime\u003c/li\u003e\n\t\u003cli\u003eFixed block memory allocator in C++\u003c/li\u003e\n\t\u003cli\u003eCompact implementation\u003c/li\u003e\n\u003c/ul\u003e\n\n## Asynchronous Multicast Delegates in C++\n\n\u003cul\u003e\n\t\u003cli\u003eImplemented in C++\u003c/li\u003e\n\t\u003cli\u003eC++ delegate paradigm\u003c/li\u003e\n\t\u003cli\u003eAny callback function type (member, static, free)\u003c/li\u003e\n\t\u003cli\u003eMultiple callback arguments supported (up to 5)\u003c/li\u003e\n\t\u003cli\u003eCallback argument any type (value, reference, pointer, pointer to pointer)\u003c/li\u003e\n\t\u003cli\u003eCallback argument data copied with copy constructor\u003c/li\u003e\n\t\u003cli\u003eType-safety provided by templates\u003c/li\u003e\n\t\u003cli\u003eHeavy use of templates\u003c/li\u003e\n\t\u003cli\u003eDynamic list of registered subscriber callbacks\u003c/li\u003e\n\t\u003cli\u003eNumber of registered subscribers expands at runtime\u003c/li\u003e\n\t\u003cli\u003eFixed block memory allocator in C++\u003c/li\u003e\n\t\u003cli\u003eLarger implementation\u003c/li\u003e\n\u003c/ul\u003e\n\n## Asynchronous Multicast Delegates in Modern C++\n\n\u003cul\u003e\n\t\u003cli\u003eImplemented in C++ (i.e., C++17)\u003c/li\u003e\n\t\u003cli\u003eC++ delegate paradigm\u003c/li\u003e\n\t\u003cli\u003eFunction signature delegate arguments\u003c/li\u003e\n\t\u003cli\u003eAny callback function type (member, static, free)\u003c/li\u003e\n\t\u003cli\u003eMultiple callback arguments supported (N arguments supported)\u003c/li\u003e\n\t\u003cli\u003eCallback argument any type (value, reference, pointer, pointer to pointer)\u003c/li\u003e\n\t\u003cli\u003eCallback argument data copied with copy constructor\u003c/li\u003e\n\t\u003cli\u003eType-safety provided by templates\u003c/li\u003e\n\t\u003cli\u003eHeavy use of templates\u003c/li\u003e\n\t\u003cli\u003eVariadic templates\u003c/li\u003e\n\t\u003cli\u003eTemplate metaprogramming\u003c/li\u003e\n\t\u003cli\u003eDynamic list of registered subscriber callbacks\u003c/li\u003e\n\t\u003cli\u003eNumber of registered subscribers expands at runtime\u003c/li\u003e\n\t\u003cli\u003eCompact implementation (due to variadic templates)\u003c/li\u003e\n\u003c/ul\u003e\n\n# Conclusion\n\n\u003cp\u003eI\u0026rsquo;ve done quite a bit of multithreaded application development over the years. Invoking a function on a destination thread with data has always been a hand-crafted, time consuming process. This library generalizes those constructs and encapsulates them into a user-friendly delegate library.\u003c/p\u003e\n\n\u003cp\u003eThe article proposes a C++ multicast delegate implementation supporting synchronous and asynchronous function invocation. Non-blocking asynchronous delegates offer fire-and-forget invocation whereas the blocking versions allow waiting for a return value and outgoing reference arguments from the target thread. Multicast delegate containers expand the delegate\u0026rsquo;s usefulness by allowing multiple clients to register for callback notification. Multithreaded application development is simplified by letting the library handle the low-level threading details of invoking functions and moving data across thread boundaries. The inter-thread code is neatly hidden away within the library and users only interact with an easy to use delegate API.\u003c/p\u003e\n\n# \u003ca name=\"References\"\u003eReferences\u003c/a\u003e\n\n\u003cul\u003e\n\t\u003cli\u003e\u003ca href=\"https://www.codeproject.com/Articles/5277036/Asynchronous-Multicast-Delegates-in-Modern-Cpluspl\"\u003e\u003cstrong\u003eAsynchronous Multicast Delegates in Modern C++\u003c/strong\u003e\u003c/a\u003e\u0026nbsp;- by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003ca href=\"https://www.codeproject.com/Articles/5262271/Remote-Procedure-Calls-using-Cplusplus-Delegates\"\u003e\u003cstrong\u003eRemote Procedure Calls using C++ Delegates\u003c/strong\u003e\u003c/a\u003e\u0026nbsp;- by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003ca href=\"https://www.codeproject.com/Articles/1272894/Asynchronous-Multicast-Callbacks-in-C\"\u003e\u003cstrong\u003eAsynchronous Multicast Callbacks in C\u003c/strong\u003e\u003c/a\u003e - by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003ca href=\"https://www.codeproject.com/Articles/1092727/Asynchronous-Multicast-Callbacks-with-Inter-Thread\"\u003e\u003cstrong\u003eAsynchronous Multicast Callbacks with Inter-Thread Messaging\u003c/strong\u003e\u003c/a\u003e - by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003ca href=\"https://www.codeproject.com/Articles/1191232/Type-Safe-Multicast-Callbacks-in-C\"\u003e\u003cstrong\u003eType-Safe Multicast Callbacks in C\u003c/strong\u003e\u003c/a\u003e - by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003ca href=\"https://www.codeproject.com/Articles/1165243/Cplusplus-State-Machine-with-Asynchronous-Multicas\"\u003e\u003cstrong\u003eC++ State Machine with Asynchronous Multicast Delegates\u003c/strong\u003e\u003c/a\u003e - by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003ca href=\"http://www.codeproject.com/Articles/1084801/Replace-malloc-free-with-a-Fast-Fixed-Block-Memory\"\u003e\u003cstrong\u003eReplace malloc/free with a Fast Fixed Block Memory Allocator\u003c/strong\u003e\u003c/a\u003e - by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003ca href=\"http://www.codeproject.com/Articles/1095196/Win32-Thread-Wrapper-with-Synchronized-Start\"\u003e\u003cstrong\u003eWin32 Thread Wrapper with Synchronized Start\u003c/strong\u003e\u003c/a\u003e - by David Lafreniere\u003c/li\u003e\n\t\u003cli\u003e\u003cstrong\u003e\u003ca href=\"https://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible\"\u003eMember Function Pointers and the Fastest Possible C++ Delegates\u003c/a\u003e\u003c/strong\u003e - by Doug Clugston\u003c/li\u003e\n\u003c/ul\u003e\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fendurodave%2Fasyncmulticastdelegatecpp11","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fendurodave%2Fasyncmulticastdelegatecpp11","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fendurodave%2Fasyncmulticastdelegatecpp11/lists"}