Wednesday, April 29, 2009

read and write UNICODE file in Python

Lately I found need to delete blank line in a text file. what's special is that the file is encoded in utf-16le, rather than ascii. After some trials, the following
script does the job nicely.


import sys
import codecs

print(sys.getdefaultencoding())
print(sys.version_info)

raw = codecs.open(r'd:/u','rb','utf16')
out = []
for line in raw:
if line.lstrip():
out.append(line)
codecs.open(r'd:/uu','w','utf16').writelines(out)
print('OK')

Wednesday, April 1, 2009

Serialize class member function invocations in C++ with Boost.Thread

Here's the scenario, you have a class that wraps the communication through one USB port, with each member sending one application-specific command(e.g. start/stop device, turn on LED etc ). Usually, the invocations of these member functions need to be mutual exclusive due to the fact that the USB port can only work on one thing at one time. This is not a problem in a single-threaded environment, but a real challenge in a multi-threaded word: what if you have a always-running thread of one member function being dedicated to polling the device, while you need to send other commands to the device on demand?

As this example shows, they will very likely step on each other's feet.



#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

using std::cout;

class USB
{
public:

void poll()
{
cout << "poll@thread="
<< boost::this_thread::get_id()
<< std::endl;
}
void start()
{
cout << "start@thread="
<< boost::this_thread::get_id()
<< std::endl;
}

void stop()
{
cout << "stop@thread="
<< boost::this_thread::get_id()
<< std::endl;
}

void pause()
{
cout << "pause@thread="
<< boost::this_thread::get_id()
<< std::endl;
}
};

int main(int argc, char* argv[])
{
USB usb;
boost::thread_group threads;

threads.add_thread(new boost::thread(&USB::start, &usb));
threads.add_thread(new boost::thread(&USB::poll, &usb));
threads.add_thread(new boost::thread(&USB::pause, &usb));
threads.add_thread(new boost::thread(&USB::stop, &usb));

threads.join_all();
}

// outputs:

//D:\>usb
//start@thread=poll@thread=pause@thread=stop@thread=00143318
//001432E8001432B800143288
//
//
//
//
//D:\>




The solution is quite simple: add a mutex as a class member so that you can make any two functions mutual exclusive:


#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

using std::cout;

class USB
{
public:

void poll()
{
boost::mutex::scoped_lock l(m_mutex);

cout << "poll@thread="
<< boost::this_thread::get_id()
<< std::endl;
}
void start()
{
boost::mutex::scoped_lock l(m_mutex);

cout << "start@thread="
<< boost::this_thread::get_id()
<< std::endl;
}

void stop()
{
boost::mutex::scoped_lock l(m_mutex);

cout << "stop@thread="
<< boost::this_thread::get_id()
<< std::endl;
}

void pause()
{
boost::mutex::scoped_lock l(m_mutex);

cout << "pause@thread="
<< boost::this_thread::get_id()
<< std::endl;
}
private:
boost::mutex m_mutex;
};

int main(int argc, char* argv[])
{
USB usb;
boost::thread_group threads;

threads.add_thread(new boost::thread(&USB::start, &usb));
threads.add_thread(new boost::thread(&USB::poll, &usb));
threads.add_thread(new boost::thread(&USB::pause, &usb));
threads.add_thread(new boost::thread(&USB::stop, &usb));

threads.join_all();
}

// outputs:

//D:\>usb
//start@thread=00143288
//poll@thread=001432B8
//pause@thread=001432E8
//stop@thread=00143318
//
//D:\>


It's also possible to only make just two functions mutual exclusive:

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

using std::cout;

class USB
{
public:

void poll()
{
//boost::mutex::scoped_lock l(m_mutex);

cout << "poll@thread="
<< boost::this_thread::get_id()
<< std::endl;
}
void start()
{
boost::mutex::scoped_lock l(m_mutex);

cout << "start@thread="
<< boost::this_thread::get_id()
<< std::endl;
}

void stop()
{
boost::mutex::scoped_lock l(m_mutex);

cout << "stop@thread="
<< boost::this_thread::get_id()
<< std::endl;
}

void pause()
{
//boost::mutex::scoped_lock l(m_mutex);

cout << "pause@thread="
<< boost::this_thread::get_id()
<< std::endl;
}
private:
boost::mutex m_mutex;
};

int main(int argc, char* argv[])
{
USB usb;
boost::thread_group threads;

threads.add_thread(new boost::thread(&USB::start, &usb));
threads.add_thread(new boost::thread(&USB::poll, &usb));
threads.add_thread(new boost::thread(&USB::pause, &usb));
threads.add_thread(new boost::thread(&USB::stop, &usb));

threads.join_all();
}

// outputs:
//D:\>usb
//start@thread=poll@thread=pause@thread=001432E8001432B800143288
//stop@thread=00143318
//
//
//
//D:\>


In the code above, only start() and stop() are mutual exclusive.