:fish_cake: A new take on polymorphism in C++

Overview

DynaMix

Language Standard License Gitter

Build and Test

DynaMix (Dynamic Mixins) is a new take on polymorphism. It lets the user compose and modify polymorphic objects at run time in C++.

The library is a means to create a project's architecture rather than achieve its purpose. It focuses on maximal performance and minimal memory overhead.

DynaMix is great for the software architecture of systems with very complex objects including, but not limited to:

  • Games (especially role-playing ones or strategies)
  • CAD systems
  • Enterprise systems
  • UI libraries

The library uses the type dynamix::object as a placeholder, whose instances can be extended with existing classes (mixins), thus providing a particular instance with the functionality of all those types. Accessing the newly formed type's interface is made through messages – stand-alone functions generated by the library, which can be thought of as methods.

Here is a small example of what your code may look like if you use the library:

    // assuming my_objects.get_ally(0); is a way to get an ally to the
    // main character in a game
    dynamix::object& obj = my_objects.get_ally(0);

    // now let's make the object think some positive thoughts about the
    // main character

    think(obj); // C++ doesn't allow us to have obj.think().
                // DynaMix's messages are standalone functions

    // composition
    dynamix::mutate(obj)
        .add<flying_creature>();

    // object can now respond to fly()

    fly(obj); // ...instead of obj.fly()

    // mutation
    dynamix::mutate(obj)
        .remove<ally>()
        .add<enemy>();

    think(obj); // the same object now thinks negative thoughts about the main
                // character, since it's no longer an ally, but an enemy

Here are some of the key features of the library:

  • Compose objects from mixins at run time
  • Physically separate interface and implementation
  • Fast polymorphic calls – comparable to std::function
  • No external dependencies other than the standard library
  • Non-intrusive – mixins don't need to have a common parent or any special code inside
  • Mutate "live" objects by changing their composition at run time
  • Have multicast messages, which are handled by many mixins within an object
  • Possibility to have custom allocators to finely tune the memory and aim for cache-locality for critical parts of the code
  • Ability to have dynamic libraries that can enrich or modify objects, without modifying, or even rebuilding, the executable.
  • Thread safe message calls – as thread safe as the underlying methods.

You can also check out the talk about DynaMix from C++ Russia 2018 or the article about it in ACCU's Overload Journal from April, 2018.

C++ Russia video on YouTube

Created with DynaMix

The following projects are known to use DynaMix as a key piece of their software architecture:

There are two more known mobile games in development which use it. They will be added to this list upon release.

Documentation

The full documentation is available at the GitHub page of the library

Tutorials

Several small fully working annotated tutorial programs are provided with the library:

  • Basic – a program which illustrates the basic usage of DynaMix. It's a tutorial on creating mixins and messages, and creating and modifying (or mutating) objects.
  • Messages – a tutorial which takes a deeper look at creating and calling the various types of messages.
    • Message bids – a tutorial which takes a deeper look at calling and overriding messages.
  • Mutation – a tutorial about the various ways by which objects can be created and mutated.
    • Mutation rules – a deeper look at the library's capabilities for automatic object mutation.
  • Combinators – a tutorial about handling the return type of multicast messages.
  • Allocators – a tutorial about using the library's mixin allocators.
  • Serialization – a tutorial which looks at the possibilities available for serializing objects.

Building

There is an accompanying CMakeLists.txt file in the repo. Use CMake to generate project or make files for your desired platform and compiler.

Contributing

Contributions in the form of issues and pull requests are welcome.

License

This software is distributed under the MIT Software License.

See accompanying file LICENSE or copy here.

Copyright © 2013-2021 Borislav Stanimirov, Zahary Karadjov

Logo

The DynaMix logo is licensed under a Creative Commons Attribution 4.0 International License. Copyright © 2018 area55git

License: CC BY 4.0.

Boost.Mixin

DynaMix was initially developed as Boost.Mixin but is now a separate library, that doesn't depend on the Boost libraries Collection.

DynaMix, unlike Boost.Mixin, has no C++98 support. It's C++11 only.

DynaMix is distributed under the MIT license, whereas Boost.Mixin is distributed under the Boost Software License.

Footer

Comments
  • Logo Prosal for Dynamix

    Logo Prosal for Dynamix

    Hi @iboB, I'm a graphic designer and I like to collaborate with open source projects. Do you know that the graphic image of a project is very important? thinking about it I would like to design a logo for your Project Dynamix.

    I will be pleased to collaborate with you.

    question 
    opened by area55git 22
  • Allow methods from base classes to implement messages without `using`

    Allow methods from base classes to implement messages without `using`

    The problem is basically this:

    class a {
    public:
        void foo(); 
    };
    
    class b : public a {};
        
    decltype(&b::foo); // -> void (a::*)()
    

    The caller in the message macros gets instantiated with as <Mixin, Ret, Ret (PARENT::&Method)(args)> and cannot be implicitly cast to <Mixin, Ret, Ret (Mixin::&Method)(args)> .

    An explicit cast needs to be added in get_caller_for

    bug 
    opened by iboB 5
  • multicast with default impl?

    multicast with default impl?

    I'm experimenting with your library and I like the design. But I've come across an error in my editor implementation and I'm not sure how to handle that.

    Basically I have a basic object in which I can add mixins. And I have multicast messages for different purposes (showing gui stuff for example). Now when I create a new (empty) object and send a multicast message I get a "bad_message_call" exception because the object has no mixins in the initial state. Should I add a "default" mixin with empty implementations, is there something similar to default-implementation for multicast messages or should it be allowed to send multicast messages to empty objects?

    enhancement question 
    opened by questor 3
  • Users report greatly increased compilation times with template messages compared to macro messages

    Users report greatly increased compilation times with template messages compared to macro messages

    In https://github.com/iboB/dynamix/commit/79677e95655a4e02fb6780be2bf5fa8b3ea59359 the bulk of the message call code was moved into variadic template classes and out of the macros. This allowed better debugging of messages as a step-in takes you directly into debuggable C++ code instead of a macro.

    However there are user reports of 3-5 times slower builds with gcc and clang with this new feature.

    (Curiously msvc 2013 and 2015 builds don't seem affected by this. 2017 hasn't been tested yet)

    research 
    opened by iboB 1
  • Removing typeid breaks mixins in namespaces

    Removing typeid breaks mixins in namespaces

    namespace foo
    {
    DEFINE_MIXIN(bar, ...);
    }
    

    With the current macros and no typeid this sets the name "bar" to the mixin. Previously it used to be "foo::bar". Not only does this break backwards compatibility but also, name clashes will ensue of different mixins in different namespaces with the same name.

    Reverting to typeid seems like the only solution.

    bug 
    opened by iboB 1
  • Forwarding multicast arguments causes the move constructor to be called

    Forwarding multicast arguments causes the move constructor to be called

    Calling a multicast with an argument by value calls the move constructor on the first call in the chain. This isn't a problem with simple types whose move constructors don't destroy the source but can cause bugs if the source is destroyed (with a vector for example)

    Example repro:

    DYNAMIX_MULTICAST_MESSAGE_1(void, testv, vector<int>, data);
     
    class a
    {
    public:
        void testv(vector<int> data)
        {
            cout << "a: " << data.size() << endl;
        }
    };
     
    DYNAMIX_DEFINE_MIXIN(a, testv_msg);
     
    class b
    {
    public:
        void testv(vector<int> data)
        {
            // vector is destroyed here
            cout << "b: " << data.size() << endl;
        }
    };
     
    DYNAMIX_DEFINE_MIXIN(b, testv_msg);
     
     
    int main()
    {
        auto hero = new dynamix::object;
        dynamix::mutate(hero)
            .add<a>()
            .add<b>();
     
        vector<int> foo = {1, 2, 3};
        testv(hero, foo);
     
        return 0;
    }
     
    DYNAMIX_DEFINE_MESSAGE(testv);
    
    bug 
    opened by iboB 1
  • Crash when calling an unregistered message

    Crash when calling an unregistered message

    If a message is unregistered (ie no mixin implements it, and it doesn't have a default implementation) a crash occurs when it's called for an object. Instead bad_message_call should be thrown.

    bug 
    opened by iboB 1
  • Document default behaviour for missing message implementations

    Document default behaviour for missing message implementations

    Very nice library! As i can see the usual behaviour for calling a message to a mixin that does not implement it is throwing an exception, wich is nice.

    As an alternative i can define DYNAMIX_NO_MSG_THROW

    to trigger assertions instead.

    What about an option to simply doing nothing in the case the message is not implemented?

    That could be compilation unit defined or mixin defined or "interface" defined.

    That would be helpful in calling a message for each element of a vector of objects of wich only some implements a certain interface.

    (Try-catching would be time wasteful)

    documentation 
    opened by sjeps 1
  • Reduce excessive getting of mixin type infos from domain by id

    Reduce excessive getting of mixin type infos from domain by id

    Due to an old (and dropped) requirement to allow the same mixin to be instantiated multiple times from static libraries in many places of the code even though an instance of mixin_type_info is available, it is still obtained from the domain by using the id only. This is a needless indirection now and can be removed.

    refactoring 
    opened by iboB 0
  • Ditch type_info

    Ditch type_info

    Using type info is a convenient way to get mixin names, but it has its limitations. For a small price on feature parsing / registration (all at global scope) we could ditch the type info requirement and remove the limitations associated with it (when using type info mixins must be classes and never structs) by getting the mixin name from the definition macro.

    enhancement 
    opened by iboB 0
  • Investigate suppressed -fsanitize leaks

    Investigate suppressed -fsanitize leaks

    Executables which have plugins, report leaks at exit. They are suppressed for now, since it's not obvious what causes them and they are small, and seem insignificant. The most likely culprit is the lack of proper shutdown of plugins (for which we can do nothing). However an investigation for what causes them is needed in case we can do something.

    research 
    opened by iboB 0
  • v2.0

    v2.0

    It is time for v2.0 to address deficiencies in the current design.

    Concrete things:

    • Use C++17 this is a long way into the future, so why not...
    • #24
    • #25
    • #26
    • Better header structure
    • Improve design of public and private data for objects (no more #define internal public)
    • Mixin/Message domains – sets of mixins and messages that cannot be mixed. Will throw a runtime error when trying to combine certain mixins or messages.
    • Address serialization better
    • Allocator extension
    • Mixin class which holds information for mixin
    • Get implementers for msg as mixin ids
    • Allocators for absolutely everything
    • Allow onMutated private message
    • Compilation performance benchmarks
    • Logging and debug information prints
    • fuzzing
    • Package managers and cmake install
    • coverage
    • Optimize mutation process: less allocations. Design special mixin_collection for the process, that can be preallocated (or that uses a buffer that's allocated only once) and has reserve. Allow reuse of single_object_mutator.
    • Add a new mixin feature fact. Facts are static const variables in a mixin. No multicasts. No virtual tables.
    • Reflection. Call messages by string.
    v2.0 
    opened by iboB 0
  • Investigate ways to reduce the memory footprint of object_type_info

    Investigate ways to reduce the memory footprint of object_type_info

    object_type_info in a system with many messages (4096) and mixins (1024) can reach 200 KB per instance. With many mutations the types can reach hundreds which ends-up taking tens of megabytes.

    Investigate ways to make the memory footprint smaller.

    Also garbage collecting unused type infos.

    research 
    opened by iboB 0
Releases(v1.3.9)
  • v1.3.9(Nov 4, 2019)

  • v1.3.8(Nov 2, 2019)

    • Added mixin move assignment to mixin type info
    • Added object::move_matching_from which move-assigns matching mixins from one object to another
    • Exposed copy assignment and move constructor in public mixin type info
    • Fixed some unused variable warnings
    Source code(tar.gz)
    Source code(zip)
  • v1.3.7(Nov 11, 2018)

    • Properly fixed problems with messages to methods from parent classes, removing the need for from_parent
    • User config macro DYNAMIX_NO_BAD_MULTICASTS allowing safe mutlicasts (no throwing if there's no implementation)
    • Optional split-message macros to allow message implementations to be hidden for faster compilation.
    • Renamed internal macros to start with I_ instead of underscore and capital letter
    Source code(tar.gz)
    Source code(zip)
  • v1.3.6(Jul 7, 2018)

    • New mixin feature mixin_name allows custom mixin names
    • Fixed short message macros
    • The metric object_type_info::num_objects is always on
    • Domain has a method which frees resources for unused object type infos
    • Allowed using the legacy message macros since clang and gcc may suffer increased compilation time with the new ones
    • Fixed a variable shadowing warning in domain.hpp
    • Added multi-threaded and mixin-in-namespace tests
    • Added a compiler performance benchmark
    • Improved build time of tests
    Source code(tar.gz)
    Source code(zip)
  • v1.3.5(Mar 26, 2018)

  • v1.3.4(Feb 26, 2018)

    • Exceptions are no longer derived from std::exception
    • Added a way to refere to a message for a parent as a workaround to issue #20
    • Fixed visibility for clang builds on macOS
    • Added an optional header with message macros with short names
    • Removed noncopyable class
    • CI tests of DynaMix as a static library
    Source code(tar.gz)
    Source code(zip)
  • v1.3.3(Feb 6, 2018)

  • v1.3.2(Jan 16, 2018)

  • v1.3.1(Jan 15, 2018)

    • Reduced macro-generated code by message declaration macros. Messages are now easier to debug with only a single line in the macro when stepping.
    • Fixed a bug which didn't allow message overloads on constness alone
    • Added a getter for the mutation from mutator classes
    • Improved performance tests
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Dec 19, 2017)

    • Redesign of allocators. The new allocators are not backwards compatible.
      • Added per-object allocators which can allocate mixins for a specific object. This can be useful if you want all mixins for an object to be in a single contiguous memory block.
      • New allocators have much more flexibility as they receive more information when allocating, including a pointer to the associated object
      • New allocators can construct and destroy mixins
    • Added methods to object which allow users to replace mixins within objects
    • Split mixin_type_info into a public and private part
    • Added noexcept specifiers to some methods where appropriate
    Source code(tar.gz)
    Source code(zip)
  • v1.2.3(Oct 28, 2017)

  • v1.2.2(Oct 18, 2017)

  • v1.2.1(Oct 15, 2017)

    • Improved mutation rules: They can now be added, removed and persisted via shared pointers
    • Added object::has and object::get with const char* to query mixins by name
    • add_new_mutation_rule is now deprecated
    • Fixed library version header
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Aug 17, 2017)

    • Introduced a new feature: Message bids
      • Overriding multicast functions is now possible
      • Added DYNAMIX_CALL_NEXT_BIDDER which works for unicasts and multicasts
      • Added bids tutorial
    • Dropped CMake 2.x support. Transition to modern CMake (3.2+)
    • Fixed a bug which caused a leak when defining an invalid type (when a mutation causes an exception to be thrown)
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Apr 7, 2017)

    • Dropped support for an obscure optimization feature which allowed for the same mixins and messages to be defined multiple times in multiple modules (i.e. in a static library linked to those modules)
    • Fixed bug with crashes when unloading and then reloading a plugin which defines a message.
    • Fixed various bugs with unused (which no mixin features) messages:
      • obj.implements(unused_msg) caused a crash
      • unused(obj ...) cause a crash (instead of exception)
      • Crash when only a plugin uses the message
    • Added (optional) mutation thread safety; in that mutating two different objects in two different threads is now safe.
    • Added optional additional metrics to object and mixin type data to show the number of objects and mixins, respectively, of a given type.
    Source code(tar.gz)
    Source code(zip)
Owner
Borislav Stanimirov
A (mostly) C++ programmer
Borislav Stanimirov
this project is a function in c to take the next line of a file or a file descriptor. this is a project of 42 school.

Get Next Line of 42. Make with ❤︎ for Luiz Cezario ?? Index What's this Repo? List of Archives Technologies How to Run Find a Bug? Or somenthing need

Luiz lima cezario 7 Nov 28, 2022
A simple take-out delivery system written by C

Take-out delivery system ?? BUPT Course: Introduction to Computing and Foundation of Programming A simple take-out delivery system written in C. ?? In

T_Y_H 2 Oct 3, 2021
This Repo would take notes for some OCW courses which I consider it is excellent.

Excellent OCW This Repo would take notes for some OCW courses which I consider it is excellent. Course Code HomePage Assignment&Note [Done] MIT 6.S096

PeterWrght 3 Apr 24, 2022
Take Damage hook hook made to increase weapon damage, the game I made is Free Fire in version 1.65

Take-Damage Simple Take Damage hook hook made to increase weapon damage, the game I made is Free Fire in version 1.65 Bool bool isTakeDemageBool = fal

Master Games 3 Jan 1, 2022
Electrostatic Discharge (esd) is here to take the pain out of making static websites.

Electrostatic Discharge (esd) is here to take the pain out of making static websites. It's a minimal templating tool for html, css and javascript.

xoorath 12 Nov 27, 2022
This is our take on the digitalisation of the board game "b00le0", where you can play versus our AI, or against one of your friends in an online match.

This is our take on the digitalisation of the board game "b00le0", where you can play versus our AI, or against one of your friends in an online match.

valko purzalko 22 Dec 8, 2022
Servo library with stm developed by the Liek Software Team. We are working on new versions.

Liek-Servo-Library Liek Servo Library is a library that makes it easy for you to drive servo motors with STM32F10x series cards. The library is still

null 14 Nov 4, 2022
PoC: Rebuild A New Path Back to the Heaven's Gate (HITB 2021)

wowGrail Rebuild a new to Abuse the conversion layer embedded in WOW64(Windows 32 on Windows 64), that makes malware able to launch 32-bit NTAPI inter

Sheng-Hao Ma 91 Dec 11, 2022
SMARTmBOT - a new, customizable, scalable, and fully opensource mobile robot platform

The goal of this repository is to introduce a new, customizable, scalable, and fully opensource mobile robot platform, called SMARTmBOT. This repository provides a guide, and all design files and source codes so that you can build your own SMARTmBOT. SMARTmBOT can be useful for studying the basics of robotics, especially mobile robotics. It can also be used to study advanced topics such as swarm robotics.

SMART Lab at Purdue University 39 Jan 2, 2023
Audacity fork without Telemetry and with new features

Audacity fork without Telemetry and with new features

Sartox Free Software 705 Jan 3, 2023
Optimized, fast and unsafe Uniswap sniping bot for buying new listings.

Optimized, fast and unsafe Uniswap sniping bot for buying new listings. Table of content How does it work? Pregeneration Used libraries Project struct

Sebastian Szczepański 159 Dec 21, 2022
New lateral movement technique by abusing Windows Perception Simulation Service to achieve DLL hijacking code execution.

BOF - Lateral movement technique by abusing Windows Perception Simulation Service to achieve DLL hijacking ServiceMove is a POC code for an interestin

Chris Au 190 Nov 14, 2022
A new JS script plugin for flutter

js_script Run JS script. Usage // Create a JS context. JsScript script = JsScript(); // Define a class. var classInfo = ClassInfo<TestClass>( newI

null 5 Mar 8, 2022
A template for creating new MOLA modules

mola-foo Write me! Provided MOLA modules: Foo, type Foo. Build and install Refer to the root MOLA repository. Docs and examples See this package page

The MOLA SLAM framework 7 Oct 23, 2021
A new Discord client made in C++ and Qt

Fast-Discord For now it is very basic Origins of this project Coding conventions License Contact This project is really huge and requires a lot of tim

Yoen 145 Dec 31, 2022
This is new projec based in apps to chat or messages people to people

Stranger This is new projec based in apps to chat or messages people to people Esta aplicacion tendra las siguientes caracteristicas: 1* Es 100% segur

Juan Duque 3 Nov 3, 2021
New version of the well known ESP32 Radio. Now optional I2S output!

ESP32Radio-V2 New version of the well known ESP32 Radio. Now optional I2S output! Compile time configuration in config.h. Do not forget to upload the

Ed Smallenburg 56 Dec 28, 2022
New linux driver and tools for RME HDSPe sound cards and extension modules

snd-hdspe New linux kernel ALSA driver for RME HDSPe MADI / AES / RayDAT / AIO and AIO Pro sound cards and extension modules. In addition to the funct

Philippe Bekaert 25 Dec 21, 2022
Module Stomping, No New Thread, HellsGate syscaller, UUID Shellcode Runner for x64 Windows 10!

Ninja UUID Shellcode Runner Module Stomping, No New Thread, HellsGate syscaller, UUID Shellcode Runner for x64 Windows 10! Now supports running Cobalt

Bobby Cooke 362 Dec 30, 2022