{"id":20626208,"url":"https://github.com/mmcshane/eventbus","last_synced_at":"2025-04-15T15:14:15.184Z","repository":{"id":69105686,"uuid":"52111199","full_name":"mmcshane/eventbus","owner":"mmcshane","description":"A threadsafe C++ implementation of the EventBus idiom","archived":false,"fork":false,"pushed_at":"2019-08-18T13:27:17.000Z","size":270,"stargazers_count":33,"open_issues_count":0,"forks_count":7,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-15T15:14:09.445Z","etag":null,"topics":["cpp","eventbus","threadsafe"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mmcshane.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2016-02-19T19:28:25.000Z","updated_at":"2024-11-06T06:16:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"e6588867-b1ea-4c4c-a6f4-b5347ec9463c","html_url":"https://github.com/mmcshane/eventbus","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmcshane%2Feventbus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmcshane%2Feventbus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmcshane%2Feventbus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmcshane%2Feventbus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mmcshane","download_url":"https://codeload.github.com/mmcshane/eventbus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249094934,"owners_count":21211837,"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":["cpp","eventbus","threadsafe"],"created_at":"2024-11-16T13:12:17.695Z","updated_at":"2025-04-15T15:14:15.179Z","avatar_url":"https://github.com/mmcshane.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EventBus\n\nIt's an event bus. Subscribe to events. Publish events. Quoting the\n[documentation for Google's implementation of the EventBus\nconcept](https://github.com/google/guava/wiki/EventBusExplained) in\n[Guava](https://github.com/google/guava):\n\n\u003e EventBus allows publish-subscribe-style communication between components\n\u003e without requiring the components to explicitly register with one another (and\n\u003e thus be aware of each other). It is designed exclusively to replace\n\u003e traditional […] in-process event distribution using explicit registration. It\n\u003e is not a general-purpose publish-subscribe system, nor is it intended for\n\u003e interprocess communication.\n\nCaution: there are downsides to every pattern or idiom. EventBuses are no\ndifferent. [Read about some of the down-sides and alternatives](http://endlesswhileloop.com/blog/2015/06/11/stop-using-event-buses/)\nand really think about if this is an approach you want to adopt.\n\n## Features\n\nThis library is fairly small and being header-only should be easy to integrate\ninto existing projects. A C++11 compiler is required. All operations are\nthreadsafe -- establishing and/or ending subscriptions concurrent with event\npublication is safe for any number of threads. Moreover, event publication is\nwait-free _within the event bus_. It may be the case that event _handlers_ are\nnot wait-free.\n\nEvent subscriptions are aware of event-type polymorphism. That is to say that\ngiven a pair of event types called Base and Derived where Base is a base class\nof Derived, a subscription to Base event types will be invoked when an event of\ntype Derived is published. This is accomplished with a slight augmentation to\nnormal C++ inheritance -- Derived must extend Base via the\nmpm::enable_polymorphic_dispatch class rather than directly. Rather than the\nfollowing \"normal\" inheritance:\n\n~~~{.cpp}\nstruct Derived : Base\n{\n}\n~~~\n\nDerived should be defined as\n\n~~~{.cpp}\nstruct Derived : mpm::enable_polymorphic_dispatch\u003cDerived, Base\u003e\n{\n}\n~~~\n\nDefining Derived in this manner will allow and event of this type to be\ndelivered as both Derived and Base.\n\nIt is not required that mpm::enable_polymorphic_dispatch be used. Any instance\nof a C++ object type can be published, however if polymorphic delivery is desired\nthen mpm::enable_polymorphic_dispatch must be used.\n\n## Example Usage\n\nLet's define some events\n\n~~~{.cpp}\nstruct my_base_event : mpm::enable_polymorphic_dispatch\u003cmy_base_event\u003e\n{\n    int x = 12;\n};\n\nstruct my_derived_event\n    : mpm::enable_polymorphic_dispatch\u003cmy_derived_event, my_base_event\u003e\n{\n    int y = 5;\n};\n\nstruct my_object {};\n\nstruct my_non_polymorphic_event : my_object\n{\n    int foo = -1;\n};\n~~~\n\nHere's a quick look at publishing and subscribing to a polymorphic event\n\n~~~{.cpp}\nmpm::eventbus ebus;\n\n// two subscriptions - 1 for my_base_event and 1 for my_derived_event\n\nauto base_subscription = mpm::scoped_subscription\u003cmy_base_event\u003e {\n    ebus, [](const my_base_event\u0026 mbe) noexcept {\n        std::cout \u003c\u003c \"handling a base event\" \u003c\u003c mbe.x;\n    }\n);\n\nauto derived_subscription = mpm::scoped_subscription\u003cmy_derived_event\u003e {\n    ebus, [](const my_derived_event\u0026 mde) noexcept {\n        std::cout \u003c\u003c \"handling a derived event\" \u003c\u003c mde.y;\n    }\n);\n\n// publish\nebus.publish(my_derived_event{});\n\n// subscriptions terminate at scope exit\n~~~\n\nSome things worth noting here\n* Both event handlers will fire\n* If you have a C++14 compiler, the callback can be declared with auto (e.g.\n  const auto\u0026 event), removing the duplication in specifying the event type.\n\nFor non-polymorphic dispatch, any object type can be published and it will be\nhandled by handlers for _only_ that exact type.\n\n~~~{.cpp}\nmpm::eventbus ebus;\n\n// two subscriptions - 1 for my_object, 1 for my_non_polymorphic_event\n\nauto base_subscription = mpm::scoped_subscription\u003cmy_object\u003e {\n    ebus, [](const my_object\u0026 mo) noexcept {\n        std::cout \u003c\u003c \"handling a my_object\";\n    }\n};\n\nauto non_poly_subscription = mpm::scoped_subscription\u003cmy_non_polymorhpic_event\u003e {\n    ebus, [](const my_non_polymorphic_event\u0026 mnpe) noexcept {\n        std::cout \u003c\u003c \"handling a my_non_polymorphic_event \" \u003c\u003c mnpe.foo;\n    }\n);\n\n// publish\nebus.publish(my_non_polymorphic_event{});\n\n// subscriptions terminate at scope exit\n~~~\n\nNote with the above example that _only_ the handler for my_non_polymorphic_event\nwill fire because the inheritance relationship was not established via\nmpm::enable_polymorphic_dispatch.\n\n## Building\n\nThere's really no build needed as this is a header-only library, however if you\nwant to run the unit tests or generate docs you can use the cmake build. To\nperform an out-of-tree build\n\n~~~{.txt}\n$ cd \"$(mktemp -d)\"\n$ cmake /path/to/eventbus/repository\n$ make \u0026\u0026 make test\n$ make docs # generates doxygen documentation under $PWD/docs\n~~~\n\n## TODO\n- As it stands, publishing events from within event handlers is allowed. It's\n  not clear that this is good.\n- Implement an asynchronous publication proxy\n- Maybe allow non-noexcept subscribers but unsubscribe them if they throw?\n- Pull leftright as an external project rather than embedding it under\n  thirdparty/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmcshane%2Feventbus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmmcshane%2Feventbus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmcshane%2Feventbus/lists"}