{"id":13730562,"url":"https://github.com/mamedev/delegates","last_synced_at":"2025-05-12T22:18:28.226Z","repository":{"id":69575928,"uuid":"53726768","full_name":"mamedev/delegates","owner":"mamedev","description":"Fast delegates implementation","archived":false,"fork":false,"pushed_at":"2022-05-22T00:55:21.000Z","size":98,"stargazers_count":56,"open_issues_count":1,"forks_count":11,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-12T22:18:22.512Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mamedev.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,"zenodo":null}},"created_at":"2016-03-12T10:53:11.000Z","updated_at":"2024-09-10T04:50:00.000Z","dependencies_parsed_at":"2023-02-22T07:15:25.211Z","dependency_job_id":null,"html_url":"https://github.com/mamedev/delegates","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/mamedev%2Fdelegates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mamedev%2Fdelegates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mamedev%2Fdelegates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mamedev%2Fdelegates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mamedev","download_url":"https://codeload.github.com/mamedev/delegates/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253831017,"owners_count":21971009,"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":[],"created_at":"2024-08-03T02:01:16.600Z","updated_at":"2025-05-12T22:18:28.193Z","avatar_url":"https://github.com/mamedev.png","language":"C++","readme":"# Fast delegates implementation\n\n\n## Summary\n\nThe intention of this project is to make a fast implementation in C++17\nthat will work on multiple platforms at maximum speed.\n\nThe main code is in delegate.h and delegate.cpp, abi.h contains ABI\nfeature macros, and main.cpp contains some test cases to exercise the\ncode.\n\nStatus so far:\n\n| Compiler    | Version       | OS                   | Status                                     |\n|-------------|---------------|----------------------|--------------------------------------------|\n| MinGW GCC   | 10.3.0 x86_64 | Windows              | **MAME_DELEGATE_TYPE_ITANIUM**             |\n| MinGW GCC   | 10.3.0 i686   | Windows              | **MAME_DELEGATE_TYPE_COMPATIBLE**          |\n| MinGW clang | 12.0.0 x86_64 | Windows              | **MAME_DELEGATE_TYPE_ITANIUM**             |\n| MinGW clang | 12.0.0 i686   | Windows              | **MAME_DELEGATE_TYPE_COMPATIBLE**          |\n| clang-cl    | 12.0.0 x64    | Windows              | **MAME_DELEGATE_TYPE_MSVC** crash at Num=6 |\n| clang-cl    | 12.0.0 x86    | Windows              | **MAME_DELEGATE_TYPE_COMPATIBLE**          |\n| MSVC        | 19.29 x64     | Windows              | **MAME_DELEGATE_TYPE_MSVC** crash at Num=6 |\n| MSVC        | 19.29 x86     | Windows              | **MAME_DELEGATE_TYPE_COMPATIBLE**          |\n| GCC         | 8.3.1 x86_64  | Linux                | **MAME_DELEGATE_TYPE_ITANIUM**             |\n| GCC         | 8.3.1 i686    | Linux                | **MAME_DELEGATE_TYPE_ITANIUM**             |\n| GCC         | 10.2.1 armhf  | Linux                | **MAME_DELEGATE_TYPE_ITANIUM**             |\n| clang       | 6.0.1 x86_64  | Linux                | **MAME_DELEGATE_TYPE_ITANIUM**             |\n| clang       | 6.0.1 i686    | Linux                | **MAME_DELEGATE_TYPE_ITANIUM**             |\n| clang       | 11.0.1 armhf  | Linux                | **MAME_DELEGATE_TYPE_ITANIUM**             |\n\nUltimately, situations where **MAME_DELEGATE_TYPE_COMPATIBLE** is used\nshould be minimised.\n\n\n## Benchmarks\n\nNote that the benchmarks are outdated.\n\nDoing 100000000 to a virtual method\n\n         typedef delegate\u003cvoid(int j)\u003e callback_delegate;\n         callback_delegate cb = callback_delegate(FUNC(MyClass2::docount), \u0026mc);\n\n         typedef std::function\u003cvoid(int)\u003e callback_delegate_std;\n         callback_delegate_std  cb_std = std::bind(\u0026MyClass2::docount, \u0026mc, std::placeholders::_1);\n\nPlease note that times will be different from run to run, but values are near\n\n|Compiler | Version     | OS                   | Time fast delegates native (ns)                 |Time std::function/bind (ns)     |\n|---------|-------------|----------------------|---------------------------------:|--------------------------------:|\n|MinGW GCC| 5.3.0 x64   |Windows               | 131547400                        | 216178100                       |\n|MinGW GCC| 5.3.0 x86\t|Windows               | 131160000                        | 285218800                       |\n|Clang    | 3.8.0 x64\t|Windows               | 100766900                        | 219475700                       |\n|Clang    | 3.8.0 x86\t|Windows               |                                  |                                 |\n|GCC      | 4.9.2 ARM\t|Linux (RasPi2)        | 1120924321                       | 4146617167                      |\n|GCC      | 5.3.1 x64   |Linux                 | 139180356                        | 205068909                       |\n|Clang    | 3.7.0 x64\t|Linux                 | 140548960                        | 182060144                       |\n|Clang Apple    | 7.3.0 x64\t|OSX                   | 125145702                        | 262906798                       |\n|VS2015   | x64         |Windows               |                                  |                                 |\n|VS2015   | x86\t        |Windows               |                                  |                                 |\n|GCC      | 5.3.1 ARM64\t|Linux (Odroid-C2)     | 654185671                        | 1370827564                      |\n|GCC      | 4.9.2 MIPSEL|Linux (Creator Ci20)  | 1002793705                       | 3341533518                      |\n\nWindows machine Intel i7-4790K @4.00GHz\n\n\n## Description\n\nThere are many implementations of delegate-like functionality for\nC++ code, but none of them is a perfect drop-in fit for use in MAME.\nIn order to be useful in MAME, we need the following properties:\n\n* No significant overhead; we want to use these for memory\n  accessors, and memory accessor overhead is already the dominant\n  performance aspect for most drivers.\n\n* Existing static functions need to be bound with an additional\n  pointer parameter as the first argument. All existing\n  implementations that allow static function binding assume the\n  same signature as the member functions.\n\n* We must be able to bind the function separately from the\n  object. This is to allow configurations to bind functions\n  before the objects are created.\n\nThus, the implementations below are based on existing works but are\nreally a new implementation that is specific to MAME.\n\n--------------------------------------------------------------------\n\nThe \"compatible\" version of delegates is based on an implementation\nfrom Sergey Ryazanov, found here:\n\n[https://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates](https://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates)\n\nThese delegates essentially generate a templated static stub function\nfor each target function. The static function takes the first\nparameter, uses it as the object pointer, and calls through the\nmember function. For static functions, the stub is compatible with\nthe signature of a static function, so we just set the stub directly.\n\nPros:\n\n* should work with any modern compiler\n* static bindings are just as fast as direct calls\n\nCons:\n\n* lots of little stub functions generated\n* double-hops on member function calls means more overhead\n* calling through stub functions repackages parameters\n\n--------------------------------------------------------------------\n\nThe \"Itanium\" version of delegates makes use of the internal\nstructure of member function pointers in order to convert them at\nbinding time into simple static function pointers. This only works\non platforms where object-\u003efunc(p1, p2) is equivalent in calling\nconvention to func(object, p1, p2).\n\nPros:\n\n* as fast as a standard function call in static and member cases\n* no stub functions or double-hops needed\n\nCons:\n\n* requires internal knowledge of the member function pointer\n* only works for two popular variants of the Itanium C++ ABI\n\n--------------------------------------------------------------------\n\nThe \"MSVC\" version of delegates makes use of the internal structure\nof member function pointers in order to convert them at binding time\ninto simple static function pointers. This only works on platforms\nwhere object-\u003efunc(p1, p2) is equivalent in calling convention to\nfunc(object, p1, p2).\n\nPros:\n\n* as fast as a standard function call in static and non-virtual\n  member cases\n* no stub functions needed\n\nCons:\n\n* requires internal knowledge of the member function pointer\n* only works works with MSVC ABI, and not on 32-bit x86\n* does not work for classes with virtual bases\n* structure return does not work with member function pointers\n* virtual member function lookup cannot be done in advance\n\n--------------------------------------------------------------------\n\nFurther reading:\n\n* http://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-pointers\n  Formal specification for the most common member function pointer\n  implementations.\n\n* https://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible\n  Discusses many member function pointer implementations.  Based\n  on reverse-engineering, so not entirely accurate.  In particular,\n  various fields are incorrectly assumed to be `int`-sized which is\n  not true in the general case.\n\n* https://devblogs.microsoft.com/oldnewthing/20040209-00/?p=40713\n  Describes the MSVC implementation of pointers to member\n  functions for classes with single or multiple inheritance.  Does\n  not mention the additional variants for virtual or unknown\n  inheritance.  Incorrectly states that the \"this\" pointer\n  displacement is a `size_t` when in reality it is an `int` (important\n  for 64-bit architectures).\n\t\n\n## License (BSD-3-clause)\n\n\u003ca href=\"http://opensource.org/licenses/BSD-3-Clause\" target=\"_blank\"\u003e\n\u003cimg align=\"right\" src=\"http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png\"\u003e\n\u003c/a\u003e\n\n\tCopyright 2010-2022 Aaron Giles, Couriersud, Miodrag Milanovic, Vas Crabb.\n\tAll rights reserved.\n\t\n\tRedistribution and use in source and binary forms, with or without\n\tmodification, are permitted provided that the following conditions are met:\n\t\n\t   1. Redistributions of source code must retain the above copyright notice,\n\t      this list of conditions and the following disclaimer.\n\t\n\t   2. Redistributions in binary form must reproduce the above copyright\n\t      notice, this list of conditions and the following disclaimer in the\n\t      documentation and/or other materials provided with the distribution.\n\t\n\tTHIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR\n\tIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\tMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n\tEVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n\tINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n\t(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n\tLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n\tON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n\t(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n\tTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n","funding_links":[],"categories":["C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmamedev%2Fdelegates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmamedev%2Fdelegates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmamedev%2Fdelegates/lists"}