kivy/kivy — pull request #2797 by matham (2014-12-27 09:34:45+00:00)
Title: Restore internal EventObservers to use python objects instead of structs.

Some history, I added `fast_bind` and at the same time created the `EventObservers` class. This class provided the required behavior for this in a single place rather than doing it multiple times in Properties and EventDispatcher.

This class was initially implemented as a doubly linked list using pure c, hence its uglyness and manual GC. The initial reason for doing it in c, was that I had forgotten about GC, so it seemed a lot faster as opposed to when I used python objects to store the callbacks. But once GC was added there is no more advantage for doing it in pure c. This pr implements the doubly linked list using cython objects instead. In the process it should fix #2560 and #2768.

There are 3 stages of this commit.
- This first commit reverts all the way to use a python `list` and stores the callbacks and its args as a tuple in the list.
- The second commit modifies it to use a cython class for each callback rather than a tuple.
- The third commit uses a cython class for each callback, and stores them as a doubly linked list. This is the fastest because there's no copying cost for each binding.

Following are the benchmarks for each of the commits. As you can see, the third commit is fairly close in perf to master which used the c-struct linked list, rather than cython classes as in the third commit:

```
master	commit-1	commit-2	commit-3
1/8 Core: button creation (10000 * 10 a-z) 10.910383	11.393596	11.630502	10.770375
2/8 Core: button creation (10000 * 10 a-z), with Clock.tick 13.249346	14.025339	13.995629	14.223436
3/8 Core: label creation (10000 * 10 a-z) 8.752127	9.66303	9.644442	8.717512
4/8 Core: label creation (10000 * 10 a-z), with Clock.tick 9.847046	12.100059	12.075669	10.856569
5/8 Widget: creation (10000 Widget) 2.965653	3.428027	3.450615	2.939358
6/8 Widget: creation (10000 Widget + 1 root) 3.401442	3.928403	3.899627	3.426925
7/8 Widget: event dispatch (1000 on_update in 10*1000 Widget) 0.064709	0.067266	0.066639	0.063541
8/8 Widget: empty drawing (10000 Widget + 1 root) 0.000687	0.000651	0.000687	0.000671
Result 49.191393	54.606372	54.763809	50.998387

```