Monday, September 7, 2009

MPL Terms

In case I need to look it later,(From C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond)

metafunction

A metafunction is either

  • a class template, all of whose parameters are types

or

  • a class

with a publicly accessible nested result type called type.


metafunction class

A metafunction class is a class with a publicly accessible nested metafunction called apply.

e.g.

struct plus_f
{
template <class T1, class T2>
struct apply
{
typedef typename mpl::plus<T1,T2>::type type;
};
};

Friday, May 22, 2009

(Function Objects)Functor are faster than Functions

In my play with my pet project, I observed that functors are slightly faster that functions -- I had thought the other way around.

Here the explanation I found online:

"... consider using function objects instead of functions is faster code. The difference between a function and an object of a class that defines the member operator()() is that functions are converted to pointers when passed as arguments to other functions, thus incurring the overhead of a function call even if they are declared inline. In many cases an invocation of a function object, as in the examples on std::transform() in Section 3.2.2.1, can be expanded in-line, eliminating the overhead of a function call."

No wonder.

Wednesday, May 6, 2009

bool guard

Sometimes we need to write code like this to monitor a process
void func()
{
is_finished = false);

// do something ...

is_finished = true);
}

since the code must be written in pairs, one at the very beginning, and the other the very end, using C++ RAII idiom is a bit better.
class bool_guard
{
public:
bool_guard(bool& b, bool init_value = true):m_bool(b)
{
m_bool = init_value;
}

~bool_guard()
{
m_bool = !m_bool;
}
private:
bool& m_bool;
};


now, we can write code like this:
void func()
{
bool_guard b(false);
// do something ...
}

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.

Tuesday, March 24, 2009

The Hierarchical Concepts of USB

Although I've built some USB related products, I still get confused with some concepts about USB, esp. that ubiquitous word of "setup". Taking the time of re-writing a STMicroelectronics ST7 Tube driver to WinUSB, I sorted the concepts out in case I am lost again.

USB communications are categorized into 4 kinds of TRANSACTIONS, namely,
- Control Transfers
- Interrupt Transfers
- Isochronous Transfers
- Bulk Transfers

Each TRANSACTION is made up of raw PACKETS:
- a Token Packet (Header defining what it expects to follow),
- an Optional Data Packet, (Containing the payload) and a
- a Status Packet (Used to acknowledge transactions and to provide a means of error correction)


Each Packet is a combination of 5 FIELDS:
- Sync : Synchronising clocks
- PID : Packet ID
- ADDR : Device Address
- ENDP : Endpoit on thhis Device
- CRC
- EOP : End of Packet

And the combination is NOT random, actually only 4 of them:
- Token Packets = Sync + PID + ADDR + ENDP + CRC5 + EOP
- Data Packets = Sync + PID + Data + CRC16 + EOP
- Handshake Packets = Sync + PID + EOP
- Start of Frame Packets = Sync + PID + Frame Number + CRC5 + EOP

Sepcial notes about "SETUP":

There is a kind of PID named SETUP amongst other types such as IN and OUT, only a Token Packets has a SETUP PID.

A Token Packet with the PID being SETUP can only appear in Control Transfers, and only in the SETUP STAGE.

Control Transfers have 3 stages: SETUP, DATA, and STATUS stages. In the latter 2 stages, no Token Packets with PID being SETUP would appear. only Token Packets with PID being IN or OUT, followed by Data Packets are used.

SETUP PACKETS are packets that are sent through Control Transfers. They cover packets in all the 3 stages aforementioned, but not only the Token Packets with PID being SETUP.

SETUP PACKETS are so called because they are used to set up the device including the detection and configuration of the device and carrying out common functions such as setting the USB device’s address, requesting a device descriptor or checking the status of a endpoint. Hence the concept of STANDARD REQUESTS, namely,
STANDARD DEVICE REQUESTS:
- get_status(0x00)
clear_feature(0x01)
set_feature(0x03)
set_address(0x05)
get_descriptor(0x06)
set_descriptor(0x07)
get_configuration(0x08)
set_configuration(0x09)

- STANDARD INTERFACE REQUESTS:
get_status(0x00)
clear_feature(0x01)
set_feature(0x03)
get_interface(0x0a)
set_interface(0x11)

- STANDARD ENDPOINT REQUESTS:
get_status(0x00)
clear_feature(0x01)
set_feature(0x03)
synch_frame(0x12)


While writting software on the Host(e.g. PC), SETUP PACKETS are wrapped into data structs such as WINUSB_SETUP_PACKET in WinUSB, which correspond to the whole 3-stage Control Transfers, not the SETUP STAGE, neither the token packets with PID being SETUP.

this USB-in-a-nutshell is the best USB tutorial online and where the above info are extracted from.

Get Current Time in C++

The ATL/MFC way:
/*Output Current Time is: 03/24/09 15:54:43*/



#include <atltime.h> // for CTime

#include <atlstr.h> // for CString

#include <iostream>



int main()

{

CString s(CTime::GetCurrentTime().Format("%c"));

std::wcout << L"Current Time is: "<< s.GetString();

}







The Boost Way:

/* Uses the clock to get the local time

*

* Expected Output something like:

* 2002-Mar-08 16:30:59

*/



#include "boost/date_time/posix_time/posix_time.hpp"

#include <iostream>



int main()

{

using namespace boost::posix_time;

using namespace boost::gregorian;



//get the current time from the clock -- one second resolution

ptime now = second_clock::local_time();



std::cout << L"Current Time is: "

<< to_simple_wstring(now)

<< std::endl;

return 0;

}