Friday, May 22, 2009
(Function Objects)Functor are faster than Functions
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
{
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.
{
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:
{
bool_guard b(false);
// do something ...
}
Wednesday, April 29, 2009
read and write UNICODE file in Python
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
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++
/*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();
}
/* 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;
}