Boost logo

Boost :

Subject: [boost] [mixin] Introducing a new library.
From: Borislav Stanimirov (b.stanimirov_at_[hidden])
Date: 2013-01-30 14:53:33


Hello,

Boost.Mixin is a library I'm developing with the idea to someday submit
it to Boost.

It is an entity-component system, with full abstraction between
interface and implementation.

In short, users can define objects by combining components (often
referred to from here on out as mixins). A mixin is a regular C++ class
for which two macros are defined. The main thing however are the
messages. Instead of getting the component with some function like
`get_component` (which is possible but discouraged in the library),
users deal with objects only. They can call messages (inspired by
Smalltalk's messages) which are dynamically dispatched to the
appropriate mixin.

The messages (also defined with macros) are the only thing needed for a
user to call methods from the object's mixins. When defining a mixin,
the user tells which messages it's going to implement, and when adding
this mixin to the object a virtual table of sorts is filled and the
object starts responding to those messages by calling the mixin's actual
C++ methods.

Some of the key features are:
* Multicast messages. A message that is implemented and handled by more
than one mixin. See the message `trace` in the example. (As opposed to
unicast messages, that are handled by a single mixin)
* Object access from within the mixin. The macro `bm_this` (Boost.Mixin
this). See the renderer do in the example.
* "Live" object mutation by adding and removing mixins. As demonstrated
in `change_rendering_system` in the example. This is done via the
`object_transformer` class and is currently the only way of adding
mixins to objects.
* Mixin (and message) domains. The domain is a collection of mixins and
messages that work together. If you create a set of mixins that will
never conceivably have to exist in the same object as another set of
mixins, you should use a different domain.

Here is a github link to the library: http://github.com/iboB/boost.mixin
A working example can be found here:
http://github.com/iboB/boost.mixin/tree/master/libs/mixin/example/basic
The example is nothing more than some objects and mixins working
together as they would hypothetically in a simple game. All "game" code
has been shortcut to text outputs like: "right now an object is being
rendered by the d3d renderer". The example demonstrates most of the
currently supported library features.

There is no jamfile yet. I develop it with Qt Creator and Code::Blocks
in Linux and MS Visual Studio Express 2008 and 2012 in Windows (the
Windows projects might be somewhat outdated), so the are project files
for these four in libs/mixin/build. The same goes for the example.

I'd qualify the current state of the library as pre-alpha, so it might
have some bugs.

I also create a small performance testing project (much more is to be
added). It calls a regular function, a virtual function, `std::function`
and a unicast mixin message a hundred million times. So far I'm
generally happy with the performance, which is not to say that I won't
be working on improving it. Still my computer is the only one I've
tested it on and I'd be happy if somebody else tries the perf project.
Here are my results:

   100,000,000 x | Debug t | Release t
------------------------------------------
  regular method | 781 ms | 211 ms
  virtual method | 639 ms | 253 ms
  `std::function` | 10695 ms | 272 ms
  Mixin message | 3298 ms | 865 ms

It should also be noted that currently the library depends on a piece of
code from Don Clugston's fastdelegate (found here:
http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible).
The piece in question has been copy-pasted verbatim (wrapped around in
the boost::mixin namespace) in the third_party subfolder. Don Clugston
has done a wonderful job of creating a platform-independent
representation of C++ methods as a pair of pointers. Boost.Mixin heavily
relies on such a thing for its virtual tables.

For now I am the only developer of the library. Zahary Karadjov
(credited in the license) hasn't written anything in it yet, but he is
responsible for most of the library's public interface design, the idea
to reuse fastdelegate, and the ideas and implementation suggestions for
many of the roadmap features listed below. The programming languages
Smalltalk, Ruby, and, to a degree, Objective C have also influenced the
design.

So, here is a project roadmap of sorts:

1. Soon:
* Overloaded messages - messages that call overloaded functions. The
message's name is different for each overload but the calling function
remains the same
* Work on more sensible (and helpful) runtime and compile-time errors.
Missing messages, ambiguous message priority, etc.
* Add multicast result collectors. Like `and` or `or` for boolean return
values. Like `sum` for numeric values. Sample usage
some_multicast_message(obj, p1, p2, boost::mixin::sum). User-defined
result collectors will be possible.
* Add a new mixin feature `fact`. Facts are static const variables in a
mixin. No multicasts. No virtual tables.
* Add object type templates. Instead of manually transforming each
object, you would be able to call `type_template::new_object()`
* Add more graceful runtime error handling: default message
implementations (if none is provided), more specific non-breaking
exceptions
* Rigorous unit tests
* Performance tests
* Tutorials

2. Later:
* Boost.Jam build files
* Full reference documentation
* Formal submission to Boost??
* Call mixin constructors when mutating object or constructing them via
object type templates. Sample usage: `mutate(obj).add<mixin>("foo",
param2).add<other_mixin>(42)`
* Reduce library memory footprint
* Optional external allocators per domain. Every memory allocation
should pass through them.
* Make use of the fact that a BIG execution time improvement can be made
if a user has no mixins or messages defined in a dynamic library (and
has no plans to add such)
* Integration with Boost.Serialization. As long as the mixins of an
object are serializable, the object will be, too.
* "Static" mixins. As long as they're not mutated in or out, it provides
a faster message execution.
* Reflection. Create objects with mixins by string. Call messages by
string.
* Object mutation injections. Automatically add some mixins when others
are present. Substitute a mentioned mixin with another. Ban a mixin from
being added to an object.

3. When humankind becomes a Kardashev type two civilization:
* Integration with Boost.Thread. Call messages for a specific thread.
* User-defined message hooks. Sample implementation with messages called
on objects on another device through Boost.Asio.
* A way to mutate static mixins in and out. Slight mutation execution
penalty.
* Some magic to make it work even faster.
* Integration with Boost.Python and luabind.
* Remove C++03 backward compatibility????
* Library being accepted in Boost????

I think I will be done with the items form list one by April (some of
them are even semi-implemented) and with the items of list two by the
end of the year (and if I have more free time maybe even sooner). As for
the items in the this list... well... they are nice to think about. I do
have at least some vague ideas for each of them, but then again, this is
list three.

Any questions, comments, and suggestions are welcome.

------
Borislav Stanimirov
------
PS: Whoa. I'm sorry this post turned out so long. I didn't expect it to.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk