
Hello, Boost.Mixin is a library I'm developing and I intend to submit it for review by the end of the month (most likely on Feb, 23). Source is here: https://github.com/iboB/boost.mixin Docs are here: http://ibob.github.io/boost.mixin/ There have already been two discussion on the subject: here: http://lists.boost.org/Archives/boost/2013/01/200598.php and here: http://lists.boost.org/Archives/boost/2013/07/205184.php They showed at least moderate interest in the library. Also I had a lecture about the library back in November on Open Fest 2013 Bulgaria (Unfortunately it's in Bulgarian. If you understand Bulgarian, you can find it here http://www.youtube.com/watch?v=3sTX8lUdp1c ) The feedback from the lecture has been very positive. I'm going to complete the documentation in the following day or two (it's 90% done as of now) and then focus on docs polish, like typos, structure, etc, and fixing any bugs that might arise. The library is being used in two active closed source projects, so any major bugs are highly unlikely. Currently, apart from jamfiles, there are project files for Visual Studio 2008 and 2012, QtCreator, and Code::Blocks in the repo for your convenience. Before I submit it for a formal review, It would be great if I could have some preliminary ones. Anyone is welcome with questions, suggestions, tips, and comments Thanks, -- Borislav

On Wed, Feb 5, 2014 at 1:49 PM, Borislav Stanimirov
Currently, apart from jamfiles, there are project files for Visual Studio 2008 and 2012, QtCreator, and Code::Blocks in the repo for your convenience.
Did you consider providng CMake scritps instead of IDE-specific project files? I'm planning to review this version as soon as I can find the time.

On 5.2.2014 г. 17:27 ч., Klaim - Joël Lamotte wrote:
On Wed, Feb 5, 2014 at 1:49 PM, Borislav Stanimirov
wrote: Currently, apart from jamfiles, there are project files for Visual Studio 2008 and 2012, QtCreator, and Code::Blocks in the repo for your convenience.
Did you consider providng CMake scritps instead of IDE-specific project files?
Sure, I'll add one today or tomorrow at the very latest -- Borislav

I read most of the documentation but have limited time so I skipped a few of the last pages. Here are my notes so far: 1. The introduction page would benefit from having a short but demonstrative example before or after the list of features, but surely before getting into "comparisons". 2. There is another meaning of mixing that is D mixin, which I believe is highly differnt, but maybe a mention to clarify that it's different would help someone used to D. 3. You are talking about mixins in Ruby without a short description of what it is or any link to an explanation. 4. The introduction page have a lot of assertions about the performance of the library but no link to a page with performance comparisons. I also don't see one in the index. I would like to see one. 5. I'm not at ease with the macro defining the mixins and messages, but I'm guessing it would be hard to do otherwise... 6. In the basic example, you forgot to specify that the namespace is boost::mixin. 7. Can the definitions be inlined so that a header-only library can be implemented using boost::mixin? 8. I'm not totally sure but I find the basic example maybe a bit more complext than it could be. That's only intuition though, I don't have a specific suggestion. Yet. 9. I think I mentionned in the previous Boost.Mixin thread that I would like to have a simple way to process the full range of mixins of the same type, ignoring which objects they are "attached" to. However I don't see that feature in the documentation. The messaging system don't exactly match what I'm asking and I expect that if the user knows the exact mixin type to process it would be faster to just go through all the mixin and do the processing on each instance. This of course, assume that the mixin objects are stored "somewhere" together, per type. 10. When dispatching a message to a sequence of objects, depending on the object's mixins, it will or not do something. I would like to see a comparison of performance between messaging objects which have at least one mixin reacting to the message VS objects which have no mixin reacting to the message (but do have mixins). Basically I'm wondering if messaging cost is lower when there is no actual message handler in the mixins of an object. If not, this limits messaging to events processing (which is fine), but makes it almost impractical for mixin state updating (which is the what I want to do in [9]). 11. So far I don't see the usefulness of message priority. Could you give a demonstrative example? 12. It is not clear to me why there is need for a separate macro for const messages. 13. I feel like your game example in Tutorials is a bit flawed. For example, you use mutation to change the behaviour of the ennemy, but in the next section you explain that mutation is a slow process. Basically, that's not convincing, no game dev would do it like that I believe. However, it's only the example that is not convincing, not the principle. 14. `object_type_template` seems very important but there is no section explaining what it is and how to use it until in the middle of the second Tutorial. --- I skipped some of the pages. 15. In the Appendix you explain what an ECS is, but it's uncomplete and don't explain all the benefits. There are different types of ECS: a) component types inherit from a base type, components instances are contained/owned by the entity instance; b) same as a) but components are actually gathered in arrays by types, entities instances only have references (pointers or something else) to component instances; c) entities are just ids, components have ids, so an entity is defined by all the components having the same id; (of course there are variants of these setup) The a) solution is simple to understand. However it don't have the efficiency benefit of b) where components are gathered in arrays which are efficient to traverse with an update function (which is essential for efficiency in games). The c) solution might seem a little extreme but is actually the best way to benefit both of efficient traversing like b) and from concurrency (if you manage to have components that are truely independent) as several batches of components can be processed concurrently. Actually, c) is used in major console game engines, like the one from Naughty Dogs (Uncharted for example). The efficient processing of components is not part of your description in the ECS section, which is a problem as it is one of the two actual reasons why the ECS is actually interesting for any kind of simulation (the first reason being that it helps changing easily behaviour of entities when developing the content of the software - the composition can easily be scripted, no need to have people designing the content having to code to compose the entities). (I recommand this book[1] which have a whole chapter about this, and explains better why ECS are used in games than most of the sources I read in Further reading section.) I'm not sure what Boost.Mixin actually implements here, but if it's neither b) nor c), I would consider it unpratical in most action games. As a side note: If there is a way to achieve processing an array of components as one batch, then I would like the container of components to _not_ be global (maybe optionally), so that if I use it, I can separate the processing into several "world sections" that can be processed separately. [1] http://www.gameenginebook.com/

On 02/07/2014 09:25 PM, Klaim - Joël Lamotte wrote:
1. The introduction page would benefit from having a short but demonstrative example before or after the list of features, but surely before getting into "comparisons".
Indeed and I'll think about adding something.
2. There is another meaning of mixing that is D mixin, which I believe is highly differnt, but maybe a mention to clarify that it's different would help someone used to D.
Check. Will do.
3. You are talking about mixins in Ruby without a short description of what it is or any link to an explanation.
There's a link at the top of the page in the introduction. I'll add it to the Ruby Mixin comparison too.
4. The introduction page have a lot of assertions about the performance of the library but no link to a page with performance comparisons. I also don't see one in the index. I would like to see one.
I'm working on a more detailed performance analysis. Right now you can find some info about messages in the advanced topics here: http://ibob.github.io/boost.mixin/boost_mixin/advanced.html#boost_mixin.adva...
5. I'm not at ease with the macro defining the mixins and messages, but I'm guessing it would be hard to do otherwise...
Impossible without having the user write many tens of times as much code for defining messages, and about ten times as much for mixins.
6. In the basic example, you forgot to specify that the namespace is boost::mixin.
Check. Will do.
7. Can the definitions be inlined so that a header-only library can be implemented using boost::mixin?
Theoretically yes, however it won't be possible to use this library in another dynamic one. Since the library has a central instance (called domain) it's crucial that if two modules use mixins (say the executable and a dynamic library) they share this instance. The way to do it is if Boost.Mixin is a dynamic library used by both. So if you inline Boost.Mixin, you're bound having your software in a single module (as you are when linking statically to the library)
8. I'm not totally sure but I find the basic example maybe a bit more complext than it could be. That's only intuition though, I don't have a specific suggestion. Yet.
Are you talking about the one in Basic Usage here: http://ibob.github.io/boost.mixin/boost_mixin/basic.html ... or the one in examples here: https://github.com/iboB/boost.mixin/tree/master/libs/mixin/example/basic
9. I think I mentionned in the previous Boost.Mixin thread that I would like to have a simple way to process the full range of mixins of the same type, ignoring which objects they are "attached" to. However I don't see that feature in the documentation. The messaging system don't exactly match what I'm asking and I expect that if the user knows the exact mixin type to process it would be faster to just go through all the mixin and do the processing on each instance. This of course, assume that the mixin objects are stored "somewhere" together, per type.
This is possible with allocators. It is not the default behavior. By
default the mixins for an object are each allocated separately when
the object is construced.
You can add an allocator to a mixin (I'll add this to the documentation
in the next couple days) with
`BOOST_DEFINE_MIXIN(my_mixin, my_messages &
boost::mixin::allocator
10. When dispatching a message to a sequence of objects, depending on the object's mixins, it will or not do something. I would like to see a comparison of performance between messaging objects which have at least one mixin reacting to the message VS objects which have no mixin reacting to the message (but do have mixins). Basically I'm wondering if messaging cost is lower when there is no actual message handler in the mixins of an object. If not, this limits messaging to events processing (which is fine), but makes it almost impractical for mixin state updating (which is the what I want to do in [9]).
Calling a message for an object that doesn't implement it, is a runtime error (like calling a method for plain C++ class that doesn't implement it is a compile time error). If you want something like default message behavior whether it's nothing or something, you'll have to add mixins that implement it (with nothing or something) to your objects.
11. So far I don't see the usefulness of message priority. Could you give a demonstrative example?
For unicasts:
For temporary mutations, explained in the messages tutorial here:
http://ibob.github.io/boost.mixin/boost_mixin/tutorials.html#boost_mixin.tut...
From the page:
----------
Now lets try stunning our enemy. We'll just add the stunned_ai mixin
and, because of its special think priority, the calls to think from then
on will be handled by it.
mutate(enemy).add
12. It is not clear to me why there is need for a separate macro for const messages.
Const messages are, as you've perhaps seen, bound to const methods and generate functions whose first parameter is `const boost::mixin::object&`. Indeed you can have a single macro that does this, but it will need to have a parameter for this, say instead of BOOST_MIXIN_CONST_MESSAGE_1(void, foo, int bar); BOOST_MIXIN_MESSAGE_0(void, baz); you could have BOOST_MIXIN_MESSAGE_1(void, foo, int, bar, BOOST_MIXIN_CONST); BOOST_MIXIN_MESSAGE_0(void, baz, BOOST_MIXIN_NON_CONST); ... or something similar. I chose the first syntax.
13. I feel like your game example in Tutorials is a bit flawed. For example, you use mutation to change the behaviour of the ennemy, but in the next section you explain that mutation is a slow process. Basically, that's not convincing, no game dev would do it like that I believe. However, it's only the example that is not convincing, not the principle.
When I say "slow" I mean that it's not suitable to do for all of your objects every frame. Mutations typically lead to allocations and deallocations and that's the slowest part of them. The example's flow is something like 1. "stun" 2. ... many frames with no mutation 3. "remove stun" I should (and will) add a more detailed explanation for the mutation costs. But a couple of mutations should be able to cause a significant framerate spike (especially if you use custom allocators for some mixins you add and remove often)
14. `object_type_template` seems very important but there is no section explaining what it is and how to use it until in the middle of the second Tutorial.
It's not that much faster than the simple mutation with `mutate`. It mainly saves you from writing code and looks better. It does save you a std::map lookup, but that's not much compared to the potential allocation of mixins that will happen, whether you do use it or not.
15. In the Appendix you explain what an ECS is, but it's uncomplete and don't explain all the benefits.
Noted. I will try to expand it.
There are different types of ECS: a) component types inherit from a base type, components instances are contained/owned by the entity instance; b) same as a) but components are actually gathered in arrays by types, entities instances only have references (pointers or something else) to component instances; c) entities are just ids, components have ids, so an entity is defined by all the components having the same id;
<snip>
I'm not sure what Boost.Mixin actually implements here, but if it's neither b) nor c), I would consider it unpratical in most action games.
As a side note: If there is a way to achieve processing an array of components as one batch, then I would like the container of components to _not_ be global (maybe optionally), so that if I use it, I can separate the processing into several "world sections" that can be processed separately.
As I mentioned before. It could be something like b) but only for some mixins, that you've chosen, by adding custom allocators. Without custom allocators it is indeed neither b) nor c) -- Borislav

On Tue, Feb 11, 2014 at 7:22 AM, Borislav Stanimirov
8. I'm not totally sure but I find the basic example maybe a bit more complext than it could be. That's only intuition though, I don't have a specific suggestion. Yet.
Are you talking about the one in Basic Usage here: http://ibob.github.io/boost.mixin/boost_mixin/basic.html
Yes.
10. When dispatching a message to a sequence of objects, depending on the
object's mixins, it will or not do something. I would like to see a comparison of performance between messaging objects which have at least one mixin reacting to the message VS objects which have no mixin reacting to the message (but do have mixins). Basically I'm wondering if messaging cost is lower when there is no actual message handler in the mixins of an object. If not, this limits messaging to events processing (which is fine), but makes it almost impractical for mixin state updating (which is the what I want to do in [9]).
Calling a message for an object that doesn't implement it, is a runtime error (like calling a method for plain C++ class that doesn't implement it is a compile time error). If you want something like default message behavior whether it's nothing or something, you'll have to add mixins that implement it (with nothing or something) to your objects.
So, If I have a set of objects which I don't want to know the associated components, but I do want to send a multicast message that will be processed only by some of the components, currently I can't do this because I would get an error if one of these objects have a component which don't have a handler for that message? Isn't that limitting a lot the usage of mixins/components?
11. So far I don't see the usefulness of message priority. Could you give a demonstrative example?
For unicasts:
For temporary mutations, explained in the messages tutorial here: http://ibob.github.io/boost.mixin/boost_mixin/tutorials. html#boost_mixin.tutorials.messages
From the page:
---------- Now lets try stunning our enemy. We'll just add the stunned_ai mixin and, because of its special think priority, the calls to think from then on will be handled by it.
mutate(enemy).add
(); think(enemy); // don't do hostile stuff, because you're stunned Now let's remove the stun effect from our enemy, by simply removing the stunned_ai mixin from the object. The handling of think by enemy_ai will resume as before.
mutate(enemy).remove
(); think(enemy); // again do hostile stuff ---------- The fact that `stunned_ai` implements `think` with a higher priority helps us add it temporarily and then remove it as opposed to
1. Having to remove and re-add `regular_ai` which can potentially be a heavy or hard initializing operation 2. Taking care to remove and re-add other mixins that implement `think`, like there is in the example for `enemy_ai` and `ally_ai`
I believe that this example in practice would be implemented in another way (behaviour tree or finite state machine) so it's not really convincing in practice, but I see part of the point.
For mulitcasts:
To determine the order of execution. Like the `trace` message in the same tutorial.
Ok.
13. I feel like your game example in Tutorials is a bit flawed. For example, you use mutation to change the behaviour of the ennemy, but in the next section you explain that mutation is a slow process. Basically, that's not convincing, no game dev would do it like that I believe. However, it's only the example that is not convincing, not the principle.
When I say "slow" I mean that it's not suitable to do for all of your objects every frame. Mutations typically lead to allocations and deallocations and that's the slowest part of them.
Which is why I'm pointing to the fact that game devs would totally avoid such practice, which is why I find that example unconvincing. I'm sure another case could be found that would be more convincing.
The example's flow is something like
1. "stun" 2. ... many frames with no mutation 3. "remove stun"
If there is allocation and deallocation, it's rarely affordable for a game dev, at least in action games. To bo short, it's known to be bad practice in the field. Which is why I'm pointing that. (even if it's not an actual library problem, more a documentation problem)
I should (and will) add a more detailed explanation for the mutation costs. But a couple of mutations should be able to cause a significant framerate spike (especially if you use custom allocators for some mixins you add and remove often)
Would it be possible to avoid allocations? It looks liike this system have similar properties to Boost.Statecharts which allocate/deallocate states and use constructors and destructors as entry and exit points. I believe that Boost.MSM is actually a better (more efficient) way to do it as the whole thing is pre-allocated. I don't know how you could follow a model closer to Boost.MSM but the allocatoin/deallocatoin for a mutation seems like it could be avoided under some conditions?
15. In the Appendix you explain what an ECS is, but it's uncomplete and don't explain all the benefits.
Noted. I will try to expand it.
There are different types of ECS:
a) component types inherit from a base type, components instances are contained/owned by the entity instance; b) same as a) but components are actually gathered in arrays by types, entities instances only have references (pointers or something else) to component instances; c) entities are just ids, components have ids, so an entity is defined by all the components having the same id;
<snip>
I'm not sure what Boost.Mixin actually implements here, but if it's neither b) nor c), I would consider it unpratical in most action games.
As a side note: If there is a way to achieve processing an array of components as one batch, then I would like the container of components to _not_ be global (maybe optionally), so that if I use it, I can separate the processing into several "world sections" that can be processed separately.
As I mentioned before. It could be something like b) but only for some mixins, that you've chosen, by adding custom allocators.
Without custom allocators it is indeed neither b) nor c)
Ok that was not clear: you mean that the user have to provide allocators for mixin types to allow the behaviours of b) and c) and concurrent update of mixin instances? If yes, could you provide at least an example of upating mixing instances in a pool or something, as documentation? I think helping the user setting up easily such system would help devs getting interested in this library. Just saying that you can provide allocators suggests that you'll have to do the plumbery work to make the library work as I think most people would expect (with mixins stored in something like vectors or pools per type). Could you provide helpers for that? Thanks for your time.

On 02/11/2014 06:54 PM, Klaim - Joël Lamotte wrote:
On Tue, Feb 11, 2014 at 7:22 AM, Borislav Stanimirov
wrote: 8. I'm not totally sure but I find the basic example maybe a bit more complext than it could be. That's only intuition though, I don't have a specific suggestion. Yet.
Are you talking about the one in Basic Usage here: http://ibob.github.io/boost.mixin/boost_mixin/basic.html
Yes.
Well, it shows the most basic features. Creating messages and mixins, and creating and mutating objects with them. I don't think it can get any simpler than this. If you do have a suggestion, I'd love to hear it :)
10. When dispatching a message to a sequence of objects, depending on the
object's mixins, it will or not do something. I would like to see a comparison of performance between messaging objects which have at least one mixin reacting to the message VS objects which have no mixin reacting to the message (but do have mixins). Basically I'm wondering if messaging cost is lower when there is no actual message handler in the mixins of an object. If not, this limits messaging to events processing (which is fine), but makes it almost impractical for mixin state updating (which is the what I want to do in [9]).
Calling a message for an object that doesn't implement it, is a runtime error (like calling a method for plain C++ class that doesn't implement it is a compile time error). If you want something like default message behavior whether it's nothing or something, you'll have to add mixins that implement it (with nothing or something) to your objects.
So, If I have a set of objects which I don't want to know the associated components, but I do want to send a multicast message that will be processed only by some of the components, currently I can't do this because I would get an error if one of these objects have a component which don't have a handler for that message? Isn't that limitting a lot the usage of mixins/components?
Oh. I must have misunderstood you, then. If the message is a multicast and at least one of the mixins in the object implements it, it will be executed. When the call table for a multicast is created, the library allocates a buffer for all the message handlers in an object. So if an object has ten mixins and one of them handles a multicast message, the actual message function will end up "looping" through an array of one element. If two mixins handle it, the loop will be passed through twice, and so on. This is an exact paste from the generated calling function: for(const call_table_entry* _b_m_iter = _b_m_begin; _b_m_iter!=_b_m_end; ++_b_m_iter) { //... // the call follows _b_m_func(_b_m_mixin_data, args ); } However if no mixins in the object implement the multicast message, a runtime error will be triggered.
13. I feel like your game example in Tutorials is a bit flawed. For example, you use mutation to change the behaviour of the ennemy, but in the next section you explain that mutation is a slow process. Basically, that's not convincing, no game dev would do it like that I believe. However, it's only the example that is not convincing, not the principle.
When I say "slow" I mean that it's not suitable to do for all of your objects every frame. Mutations typically lead to allocations and deallocations and that's the slowest part of them.
Which is why I'm pointing to the fact that game devs would totally avoid such practice, which is why I find that example unconvincing. I'm sure another case could be found that would be more convincing.
The example's flow is something like
1. "stun" 2. ... many frames with no mutation 3. "remove stun"
If there is allocation and deallocation, it's rarely affordable for a game dev, at least in action games. To bo short, it's known to be bad practice in the field. Which is why I'm pointing that. (even if it's not an actual library problem, more a documentation problem)
If even a single allocation is a problem, the only solution is to use custom allocators for every mixin that may end up being mutated in or out during the main loop. I'll add a warning in the tutorial example that the mutation would lead to allocations/deallocations if no special precautions are made.
I should (and will) add a more detailed explanation for the mutation costs. But a couple of mutations should be able to cause a significant framerate spike (especially if you use custom allocators for some mixins you add and remove often)
Would it be possible to avoid allocations? It looks liike this system have similar properties to Boost.Statecharts which allocate/deallocate states and use constructors and destructors as entry and exit points. I believe that Boost.MSM is actually a better (more efficient) way to do it as the whole thing is pre-allocated. I don't know how you could follow a model closer to Boost.MSM but the allocatoin/deallocatoin for a mutation seems like it could be avoided under some conditions?
With no information about object count and size, allocations cannot be avoided. Theoretically something like `std::vector::reserve` could be implemented, but it would either need to be based on bytes (and not on mixin or object count), or would need to have complicated parameter schemes which list possible mixin configurations. The whole idea behind Boost.Mixin is to provide an alternative to the classic C++ polymorphism. Most of your examples don't need polymorphism but static types. While the library can help you a bit in such cases, its not designed to be used when polymorphism is not needed. In cases like the ones you cite, where cache locality, strongly typed references to concrete non-polymorphic classes are _crucial_, directly using the library -- objects and messages -- is simply not a good idea. The custom allocators are the only thing (at least in the foreseeable future) that can help you in similar cases. Still, since no polymorphism is needed in such a case, perhaps simply having a mixin like this: class rendering_mixin { // this member is used by the rendering system // it allocates it deallocates it and it threads // through a list of these every frame // while getting it from its object is indeed a O(1) // operation, it leads to cache misses, so use with caution rendering_implementation* _rendering; void set_rendering_implementation(rendering_implementation*); // called on reallocation void update_rendering_implementation(rendering_implementation*); } ... could be a better solution If you do need polymorphism, you're bound to have cache misses, and Boost.Mixin is an appropriate choice.
15. In the Appendix you explain what an ECS is, but it's uncomplete and don't explain all the benefits.
Noted. I will try to expand it.
There are different types of ECS:
a) component types inherit from a base type, components instances are contained/owned by the entity instance; b) same as a) but components are actually gathered in arrays by types, entities instances only have references (pointers or something else) to component instances; c) entities are just ids, components have ids, so an entity is defined by all the components having the same id;
<snip>
I'm not sure what Boost.Mixin actually implements here, but if it's neither b) nor c), I would consider it unpratical in most action games.
As a side note: If there is a way to achieve processing an array of components as one batch, then I would like the container of components to _not_ be global (maybe optionally), so that if I use it, I can separate the processing into several "world sections" that can be processed separately.
As I mentioned before. It could be something like b) but only for some mixins, that you've chosen, by adding custom allocators.
Without custom allocators it is indeed neither b) nor c)
Ok that was not clear: you mean that the user have to provide allocators for mixin types to allow the behaviours of b) and c) and concurrent update of mixin instances? If yes, could you provide at least an example of upating mixing instances in a pool or something, as documentation? I think helping the user setting up easily such system would help devs getting interested in this library. Just saying that you can provide allocators suggests that you'll have to do the plumbery work to make the library work as I think most people would expect (with mixins stored in something like vectors or pools per type). Could you provide helpers for that?
Yes, I will provide examples of allocators where the mixins to be allocated are kept in a pool. Still to update the mixin pointer within an object (something you might need on reallocation) is a feature I'm still not sure if I'll implement. So if I don't, such an allocator would need to have multiple pools (like a free list), or allocate an appropriate (huge) amount of address space, and manually manage its pages. If you're expecting to have many "holes" in you memory, a solution like the one shown above (placeholder mixin) should be implemented. -- Borislav
participants (2)
-
Borislav Stanimirov
-
Klaim - Joël Lamotte