Use boost to implement inter-class callbacks or delegates

In the software development, the pattern when one object has send a message to another object, where the object that has to be called is given to the first class somehow (usually in constructor), is quite common. In C#, the delegates serve exactly this purpose, but in C++ it is a different story.

The most common way of implementing the class-to-class callback in C++ is to define an interface, which the class that receives the event must implement:

class IInterface
{
public:
virtual void CallbackMethod() = 0;
}

class MyClass:
public IInterface
{
public:
virtual void CallbackMethod()
{
// do something useful
}

class Publisher
{
private:
IInterface* m_pCallee;
public:
Publisher(IInterface* pCallee):
m_pCallee(pCallee)
{
}

private:
void SomeMethod()
{
m_pCallee->CallbackMethod();
}
}
}

It isn’t exactly rocket science, but this method has some downsides, and some of them are quite nasty and not obvious at all. Those are:

  • You may need to define a new interface every time you need a callback function with new signature. Could partly be solved by making the interface class template
  • Each class that interested in callbacks needs to implement corresponding interface(s)
  • In some situations you may end up with a single object that can receive callbacks from many different publishers.

The last one could make you wish you never become a software programmer. The architecture, which seemed so beautiful just moments before, starts to fall into pieces once you find yourself in situation when you realize that your class-subscriber needs to receive same callbacks from different sources and act differently depending on who the caller is.

Let me explain it on the example. Imagine you have a class that implements that callback interface. You also have a lot of providers that take that interface to inform the subscribers, for example, about quote changes. But in your class, you need to track changes on, say, 10 quotes, and depending on which of those 10 changes, take different actions. So, what ’s your options?

Of course, you could just add an additional  parameter to callback method that specifies the sender, but it is not pretty at all, as the subscriber class now faces a new challenge of keeping track of all publishers it is subscribed too. Not mentioning the mess in the callback method needed to get all stuff to work!

Ideally, you want each of those providers to call different methods of your subscriber class, but in a general case it would mean 10 different interfaces and changes in all publishers, which may not be possible and I don’t even want to talk about it. The other option would be to write the proxy, which implements the basic callback interface, subscribes to the only provider and then re-routes the call to certain method on your class.

Thankfully, there is the far better option. boost::bind and boost::function are here to help.

class Publisher{
public:
typedef boost::function<void (int)> typeCallbackType;

void Subscribe(typeCallbackType cb)
{
m_cb = cb;
}

private:
typeCallbackType m_cb;

void SomeDataProcessingMethod()
{
// ....
m_cb(currentPrice);
}

}

And here is a good thing: your subscriber class does not have to implement any custom interface anymore:

class MySubscriber
{
public:
void CalledWhenPriceChanges(int newPrice)
{
// make profit here
}
}

to establish a subscription, simply use boost::bind:

Publisher* pPublisher = GetPublisherFor("someTicker");
MySubscriber Subscriber;

pPublisher->Subscribe(boost::bind(&MySubscriber::CalledWhenPriceChanges, &Subscriber, _1));

That’s all, folks!

Now, once the pPublisher has a new data, a CalledWhenPriceChanged() method of Subscriber instance of a class MySubscriber will be called. It is easy to see how additional publisher could be added if you want to monitor two tickers.

It would not only help solving the problem of multiple publishers-one subscriber. This approach will also do a great job saving you time from not having to define numbers of callback interfaces for different types of data that needs to be passed from publisher to subscriber.

Ubuntu Linux. No DMA on CD/DVD drive

Some time ago I built myself home media center on MythBuntu 8.04. It works exceptionally well… well, with one exception, if I may be excused. I could not watch my absolutely legally purchased DVDs at all – playback was choppy and jumpy, making watching movies anything but enjoyable.

If you found this post on google, you, probably, are about to give up. I was too. But I found a solution that worked for me. So, if you, like me, have seen zillions of webpages discussing the problem but none of solutions worked for you, keep reading (and please comment if this post helps you to solve your problem).

So the problem was that CD or DVD driver has no DMA enabled and hdparm would report an error:

 HDIO_SET_DMA failed: Operation not permitted

when trying to enable DMA.

I have Intel-based HP desktop with SATA HDD and IDE DVD combo drive. No problem with HDD, but DVD got stuck in PIO mode and hdparm is no help anymore. I have modules ata_piix and libata loaded.

After scanning though many discussions and FAQs, I finally found the most accurate description of the problem that offered a way to fix it. So I did exactly what they told:

# echo options libata atapi_enabled=1>/etc/modprobe.d/atapienable
# update-initramfs -u

and added

combined_mode=libata

option to kernel line in grub’s menu.lst

After reboot DVD drive was finally in UDMA mode!

MuthTV sluggish when buttons pressed on remote?

Recently I built myself a media center of old HP/Compaq computer and MythBuntu. It all worked as a top and I spent weeks learning about great features it has.

This week I was hoping to put some finishing touches on it. The last missing piece arrived – so-called “Vista Rock Remote”.

7.jpg

According to MythBunty HOWTO, this MCE-compatible remote should work out of box, despite some reviews saying it would only work with Vista. Don’t know if it works with Vista though, but it worked in MythBunty just fine. I only had to enable it in Mythbuntu control center. And restart MythTV frontend, of course.

Funnily enough, I noticed the big problem straight away. Every time I put recorded TV show on and tried to use volume up/down buttons on remote, the picture was getting sluggish and jumpy for noticeable time. Actually, it felt so weird I even thought that I might be only one who had that problem. I was not right – there were plenty of similar reports on Internet. And there was a workaround proposed also.

The root cause of the problem is that MythTV pokes X screensaver every time button on remote is pressed. It does not have to do so when you use keyboard, but must do it when you use remote as screensaver has no idea about it. MythTV kicks the screensaver by invoking “gnome-screensaver-command” with parameter –poke, and there are reports it does it twice every time you press the button. It isn’t itself a problem, the problem is that when this command is called often (and it exactly what happens when you try to put volume up or down) XOrg CPU usage jumps to 100%, which causes that unwanted “special effect” in your video.

This bug, however, has already been reported (here and here)  and the fix will probably be included in next MythTV release. For now, the only workaround was to disable screensaver and create a symbolic link to /bin/true with name gnome-screensaver-command somwehre in one of PATH’s directories that comes in front of where the original program resides. Say, if your PATH looks like

/usr/sbin;/usr/bin;/usr/local/bin

and gnome-screensaver-command is in /usr/local/bin, you can stop it from being called by creating link to /bin/true in either/usr/sbin or /usr/bin:

ln -s /bin/true /usr/bin/gnome-screensaver-command

But it would only work if you decide to disable the screensaver. You can try not to, but once display goes to sleep, you won’t be able to wake it up by using remote. So I decided to invent something more sophisticated.

Of course, I could  download sources, fix the bug and build MythTV myself, but I decided to leave it to mythbuntu team. Instead, I written small program that simply does not allow screensaver to be poked more often than once in a minute, which fixed the problem.

The good news: you can download it from this site: Mythtv screensaver proxy

The bad news: you must build it yourself. So, installing build-essentials first would be a good idea.

Download cpp file above somewhere in your home directory and then follow simple steps described in file header:

/*
 * Usage:
 *      1. execute "which gnome-screensaver-comand"
 *      If output is different from what you find below in
 *      DEF_PROGRAM, modify this macro accordingly.
 *
 *      2. build the program:
 *      g++ myth-screensaver-proxy.cpp -o gnome-screensaver-command
 *
 *      3. Find what directory original gnome-screensaver-command is in
 *              (/usr/bin/ by default).
 *
 *      4. Look at your PATH settings (printenv | grep PATH).
 *
 *      5. copy binary buld on step 2 to any of the directories that
 *      come in PATH before original gnome-screensaver-command directory.
 *
 */

A coolest gadget I ever heard of.

It seems ViewSonic wants to grab some of the pie already shared by Asus, Acer and MSI. They just announced a new netbook

I bet this computer will not leave any chances to competitiors in Russia. Its name “VieBook” sounds somewhat between “I will rock you book” and funny statement of intentions of sexual character.

Another example why global market can be a pain in the ass for marketologists.

Pause for X seconds in batch file?

Everyone who ever tried to automate routine tasks in windows knows that there is no sleep() program or its analogue. At least in default windows installation.

But there is quite an unexpected workaround:

ping -n 2 127.0.0.1 > nul

will stop batch execution for 2 seconds. (Replace 2 with your number for longer pause.)

Very simple and neat. Or is it?

Nokia N95 SIP “unable to connect to the connection server”

As many other happy owners of one of latest (well, it was released more than year ago, but it is still quite modern) gadget from Nokia, I could only use a fraction of its features, which it has in abundance. There are some rarely used (has anyone ever used “barcode scanner”? ), some just not frequent, but some of them are just not easy to use. And some have bugs despite it has been a long time since phone’s firmware was first released.

Device has WI-FI. And SIP VoIP client. And I was desperate to find a way to make cheap, or, better, free international calls. Finding VoIP provided isn’t hard – there are plenty of them around, and I am currently with JustVoIP (free landline calls to some countries, particularly to one I am interested in, guess which one), but getting communicator working with it was something similar to playing DOOM 2 on “Nightmare”. Yes, every time, again and again, I was getting wise error message “Unable to connect to the connection server”. No explanation why and what to do about it.

You, probably, already came across small truckload of Nokia SIP setup guide, but still could not get that working, as I did. Well, this is not because these guides suck, they just miss a point.

Before configuring SIP, make sure you switch Wireless power saving off. On my Nokia it was of by default, which, I guess leads session initiation to break when phone thinks nobody uses WiFi.

To switch power saving off, go to: Settings->Connection->Wireless Lan->Option->Advanced settings. Power saving option will be at the bottom, switch it off.

Now you can return to your provider’s connection guide and repeat attempt. A couple of other points I also noticed are:

  • Always enter your public name as xxxx@myvoipprovider.com, where xxx is username or SIP number they provided to you. Don’t forget to replace myvoipprovider.com with your provider’s domain name
  • It may be worthwhile using server IP address instead of domain name in proxy and registrar server options
  • I could not find how “Realm” affects the connection
  • User name is case sensitive!

In my case, justvoip started to work right after I switched power saving off. Voip quality rocks – people on the other side of globe think I somewhere much closer :)

Software engineering proverbs.

Software is Too Important to be Left to Programmers, by Meilir Page-Jones

More proverbs here.

Another joke:

Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end. (Henry Spencer)

From here.

Splashtop: Mozilla in BIOS.

It happened.

Now it is hard to get amazed by a newly released hi-tech gadget or a new “technology”. It looked like everything has already been invented, and while we discuss whether .NET framework’s performance is good or bad or what hard disk drive to buy to install Vista on it, Asus released motherboards with integrated linux.

Just imagine – you turn your PC on and desktop appears immediately with  read-to-use Web browser, Skype and more. Of course, this still looks like a toy rather a useful solution, but it depends what we want from computer. This technology exactly fits “home media center” idea – it is not a big deal to add all essential media players, photo gallery software to the flash and you’ll get a device that just works. No more worries about viruses, firewalls, malware and the whole hard disk is at your hand – operating system does not take a fraction from it, not talking about enormous tens of gigabytes needed for Windows Vista.

I don’t think Windows will die in near future, however I think such ideas can add a big nail into its coffin.

I wonder how soon we’ll see notebooks and desktops with all essential software in a flash on motherboard?

11 visitors online now
10 guests, 1 members
Max visitors today: 11 at 06:04 am MST
This month: 30 at 09-01-2010 12:31 am MST
This year: 41 at 01-23-2010 03:43 am MST
All time: 41 at 01-23-2010 03:43 am MST