Saturday, March 31, 2007

Adobe Reader crashes with SCIM

I am using Ubuntu 6.10. Recently, I have installed Adobe Reader 7.0.9. However, Adobe Reader crashed at startup. In ubuntuguide.org , it mentions Adobe Reader won't work with SCIM. Finally, I found the solution -- scim bridge. To solve the problem, install the scim-bridge package and edit the "acroread" script to insert the line "GTK_IM_MODULE=scim-bridge" at the beginning of the script, like:

#!/bin/sh
#

GTK_IM_MODULE=scim-bridge
...

Then, Adobe Reader launches normally!

Saturday, March 10, 2007

Be careful with STL strings

Please refer to the following C++ code fragment:
    char charArray[4]={'a','b','c',0,};
string str1(charArray);
string str2;
str2.append(charArray, 4);
Use the following lines to print out the contents of str1 and str2:
    cout << "str1 [" << str1 << ']' << endl;
cout << "str2 [" << str2 << ']' << endl;
The output would be:
str1 [abc]
str2 [abc]
Two strings looks same. However, does str1 equal to str2?
    cout << (str1 == str2? "equal" : "not equal") << endl;
The output:
not equal
Why not!? Let's print out the size of the strings:
    cout << "str1 size = " << str1.size() << endl;
cout << "str2 size = " << str2.size() << endl;
The output:
str1 size = 3
str2 size = 4
In short, we should be careful about the == operator of strings. It does not only compare the contents of strings, but it also compares the size of strings.

Saturday, March 03, 2007

Does it really need to Lock?

In multi-threading environment, we always face the problem of race condition -- concurrent accessing sharing data among threads. To solve the problem, we can use locking primitives, e.g. mutex, to avoid concurrent accessing of sharing data. However, those locking primitives are expensive, since they involve system calls. In some cases, we can avoid using locks.

Counting
Suppose threads updating a count variable concurrently. To avoid race condition, I saw some implementation like:
mutex.lock();
count++;
mutex.unlock();
Increment an integer just takes one CPU instruction, but locking and unlocking of mutex takes hundreds or thousands of CPU instructions. To avoid race condition, we can use atomic operations provided by CPU. Referring to /usr/include/asm-i386, there is implementation of atomic add:
static __inline__ void atomic_add(int i, atomic_t *v)
{
__asm__ __volatile__(
LOCK_PREFIX "addl %1,%0"
:"=m" (v->counter)
:"ir" (i), "m" (v->counter));
}
In Apache Portable Runtime project, it provides a set of atomic operations for different platforms.

Circular Buffers
In general, without locking, a circular buffer cannot be thread-safe. However, under a restricted condition and implementation, there would be no race condition problem. In short, for a fixed size circular buffer, if there is exactly one reader and one writer, it does not need locking. It is because the reader only updates the read-pointer and the writer only updates the write-pointer. This issue have been discussed in http://ddj.com/dept/cpp/184401814.