Tuesday, 22 September 2009

How not to use signals and slots

I wanted sound module to work for brand-new git/master Kadu with Phonon backend. So I've looked at code of sound and phonon_sound modules and I've discovered a big misuse of signal-slot mechanism.

Please look at sound.h file from 0.6.5 branch. The interesting part is signals: from SoundManager class:
signals:
  void openDeviceImpl(SoundDeviceType type,
       int sample_rate, int channels,
       SoundDevice* device);
  void closeDeviceImpl(SoundDevice device);
  void playSampleImpl(SoundDevice device,
       const int16_t* data, int length,
       bool *result);
  void recordSampleImpl(SoundDevice device,
       int16_t* data, int length, bool *result);

How this works? A module such as phonon_module creates new object that connects to these signals. Then a signal is emited and a slot is executed. Everything works, but this creates a lot of problems:
  • many object can conencts to these slots so sound may be played many times by different backend
  • so we need to ensure that only one backend is loaded, this requires additional code in module-managing classes
  • object can just ignore some signals and do not implement slots and/or connect them
  • results are returned using pointers in last parameters of these signals
This kind of problem requires another solution, that is still very simple and nice to implement:
  • create abstract class, like SoundPlayer, that has methods like SoundDevice *openDevice() and so on
  • create object SoundPlayer *Player in SoundManager
  • use this object instead of emitting signals
  • make SoundPlayer parent class of backend classes instead of connecting signals
Thats all today ;)

No comments:

Post a Comment