- We want to wrap an arbitray block of code, passing it around and execute it somewhere.
- We want that block of code still has access to it's lexical environment, name lookup still works as if it's executed where it is defined.
Etrnlog
God's in his heaven, all's right with the world.
Saturday, April 2, 2011
Closure
Saturday, March 26, 2011
Smart pointers in Qt: QScopedPointer
There're several smart pointers in Qt, among which QScopedPointer and it's pal QScopedArrayPointer are probably the most simple yet useful ones.
QScopedPointer is similar to std::auto_ptr which provides a nice way to do RAII. The most common place to use this kind of smart pointer is in a function with multiple exit points. There's a nice example in the Qt document demostrating these scenarios.
Now let's take a look at their codes and try to find something interesting :)
First, the overiew of QScopedPointer looks like this:
template <
typename T,
typename Cleanup = QScopedPointerDeleter<T>
>
class QScopedPointer
{
public:
explicit inline QScopedPointer(T *p = 0);
inline ~QScopedPointer();
// ...
protected:
T *d;
};
inline T &operator*() const
{
return *d;
}
inline T *operator->() const
{
return d;
}
// assume Foo has a member named "action" QScopedPointer pointer(new Foo()); pointer->action(); // equivalent to (pointer->action)() // thus same as ((pointer.operator->())->action)()
In a word, the operator arrow is applied recursively when the underlying object has an operator arrow. The procedure ends once the builtin operator arrow could be used (the underlying object is a pointer to a class object which has a member named "action").
It's like the "->" is not eaten up until it meets the "appropriate" "real" pointer :-)
Next let's take a look at the cleanup handler:
static inline void cleanup(T *pointer)
{
typedef char IsIncompleteType[sizeof(T) ? 1 : -1];
(void) sizeof(IsIncompleteType);
delete pointer;
}
The C++ standard says, in 5.3.5/5, "If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined". So without these weird stuffs we'll need a responsible compiler which generates a warning message in the case of an incomplete type and a responsible programmer who doesn't ignore those messages.
Another thing you might notice is that there's no assign operator from T* to QScopedPointer
For the first operator there's a "reset" function which hopefully could remind you that you are deleting the old pointer while assigning a new one.
For the second operator you can use the "take" function which means you're taking the owner ship out of the QScopedPointer. The following codes illustrate the reason:
Foo *badBar()
{
QScopedPointer<Foo> p(new Foo());
// ...
// calls the convertion operator (assuming there's one)
return p;
// but hey, the object is deleted when we leave the scope :(
}
Foo *goodBar()
{
QScopedPointer<Foo> p(new Foo());
// ...
return p.take(); // ok, QScopedPointer is no longer in charge
}
QScopedArrayPointer is just a simple refinement of QScopedPointer specifically designed for array, as it's name suggests. It overloads the operator[] for convenient.
In addition to these operators there's just a few lines playing with template partial specialization and SFINAE to make sure the type in the template argument is the same as the one you pass to the constructor. Check it out in it's code if you're interested :P
Tuesday, March 8, 2011
eBattery -- A pure simple battery monitor plasmoid
Well this actually starts when I removed polkit & consolekit from my system, and as udisks & upower depends on polkit, they are also removed. The reason why I removed them is that I already have sudo (with a config file I know exactly where it is and how to change it as I need) so I do not want another different and complex mechanism. As for udisks there's another reason: it pulls in lvm2 which is entirely useless to me.
Without upower (and without hal of course), KDE's batter monitor doesn't work anymore as hal and upower are the only backends KDE's powermanagement supports. So I write this simple plasmoid to display an icon in the system tray showing the status of the battery. It is based on sysfs interface so there's no dependency on any fancy power management backend. It looks just like the default battery monitor except that there's no interactive feature, it's just an icon :)
Download it here and run "plasmapkg -i ebat.plasmoid" to install.
Note that it only works with single battery cause I don't have any computer with multiple batteries to test it, but feel free to modify it if you need that feature as it's written in javascript and is really simple :)