Onega's profileOnegaBlogListsNetwork Tools Help

Blog


    November 30

    why do I use alloca

    alloca function allocates memory from stack, thus is much faster than heap and is released automatically when function exit. At first look it like like declare a char array, but the difference is that you can only declare array of fixed size on stack, but you can get variable size memory (although limited by available stack size) via alloca.

    #include <windows.h>
    #include <iostream>
    #include <iomanip>
    #include <exception>
    void test_stackoverflow(int size)
    {
        std::cout << __FUNCTION__ << "("<<size<<")\n";
        char* ptr = static_cast<char*>(alloca(size));
        ptr[0]='a';
        std::cout << __FUNCTION__ << "()\n";
    }

    void test_with_std_exception()
    {
        try
        {
            for(int i=102; ;i++ )
                test_stackoverflow(i*10240);
        }
        catch (std::exception& e)
        {
            std::cout << e.what()<<std::endl;
        }

    }
    void main(int argc, char* argv[])
    {
        __try{
            for(int i=102; ;i++ )
                test_stackoverflow(i*10240);

        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
            std::cout<<"Exception code 0x"<<std::hex<< _exception_code()<<std::endl;
        }
        if (argc>1)
            test_with_std_exception();
    }
    // cl -EHa overflow.cpp
    // D:\test\stl>overflow.exe
    //test_stackoverflow(1044480)
    //  Exception code 0xc00000fd

    November 17

    std::stack, std::queue and std::priority_queue

    The interesting fact is that std::queue and std::priority_queue has different interface – std::queue has front(), but std::priority_queue has top().

    #include <stack>
    #include <list>
    #include <iostream>
    #include <string>
    #include <queue>

    template<typename ContainerType>
    void fill_container(ContainerType& cnt)
    {
        cnt.push('a');
        cnt.push('0');
        cnt.push('b');
        cnt.push('c');
    }

    void main()
    {
        typedef std::stack< char, std::list<char> > char_list_stack;
        char_list_stack mystack; fill_container(mystack);
        std::cout << "\ncontent in stack:";
        while(mystack.size())
        {
            std::cout << mystack.top() << " ";
            mystack.pop();
        }

        std::queue<char, std::list<char> > myqueue;
        fill_container(myqueue);
        std::cout << "\ncontent in queue:";
        while(myqueue.size())
        {
            std::cout << myqueue.front() << " ";
            myqueue.pop();
        }

        //std::priority_queue<char, std::deque<char> > mypqueue;
        std::priority_queue<char, std::vector<char> > mypqueue;
        fill_container(mypqueue);
        std::cout << "\ncontent in priority_queue:";
        while(mypqueue.size())
        {
            std::cout << mypqueue.top() << " ";
            mypqueue.pop();
        }

    }
    // cl -EHsc stack.cpp -link -verbose:lib
    // content in stack:c b 0 a
    // content in queue:a 0 b c
    // content in priority_queue:c b a 0

    exception in ctor

    operator new return NULL if ctor throw exception, this will leads to resource leak, and other possible problem like lock is not released.

    // ctor.cpp : test throw exception in ctor.
    // cl -EHsc -d1reportSingleClassLayoutCtorWithException ctor.cpp

    #define _CRTDBG_MAP_ALLOC
    #include <tchar.h>
    #include <stdlib.h>
    #include <crtdbg.h>
    #include <iostream>
    #include <iomanip>

    class CtorWithException
    {
    public:
        CtorWithException(bool throw_exception):m_buf(new char[10240])
        {
            std::cout << __FUNCTION__ << " this=" << std::hex << (int)this <<std::endl;
            if (throw_exception)
            throw std::runtime_error("exception in ctor");
        }
        ~CtorWithException()
        {
            delete[] m_buf;
            std::cout << __FUNCTION__ << " this=" << std::hex << (int)this <<std::endl;
        }
    private:
        char* m_buf;
    };

    class TestCtorWithException
    {
    public:
        TestCtorWithException():m_buf(new char[1024*1024]),m_no_exp(false),m_has_exp(true),m_uninitialized(false)
        {
            std::cout << __FUNCTION__ << " this=" << std::hex << (int)this <<std::endl;
        };
        ~TestCtorWithException()
        {
            delete[] m_buf;
            std::cout << __FUNCTION__ << " this=" << std::hex << (int)this <<std::endl;
        };
    private:
        char *m_buf;
        CtorWithException m_no_exp;
        CtorWithException m_has_exp;
        CtorWithException m_uninitialized;
    };

    int _tmain(int argc, _TCHAR* argv[])
    {
        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT );
        TestCtorWithException* testobj=NULL;
        try
        {
            //TestCtorWithException test_obj;
            testobj=new TestCtorWithException;
        }
        catch (std::exception& e)
        {
            std::cout << e.what() << std::endl;
        }
        std::cout << "new return " << std::hex << testobj << std::endl;
        _CrtDumpMemoryLeaks();
        return 0;
    }
    // program output
    //CtorWithException::CtorWithException this=38cf34
    //CtorWithException::CtorWithException this=38cf38
    //CtorWithException::~CtorWithException this=38cf34
    //exception in ctor
    //new return 00000000
    //Detected memory leaks!
    //Dumping objects ->
    //{225} normal block at 0x00530068, 10240 bytes long.
    //Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
    //{203} normal block at 0x00420040, 1048576 bytes long.
    //Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
    //      Object dump complete.

    boost.program_options crash

    A program linking with libboost_program_options-vc90-mt-gd-1_35.lib crashed at desc.add_options(), but the release version worked. At last it turned out to be due to mixed usage of debug version CRT and release version CRT – the program in trouble linked to some release version library in its debug build. The interesting fact is that VC++ 2008 does not complain during compilation, but boost.program_options raised obscure run-time error.

    October 27

    Join sample on PostgreSQL

    Here is a simple example that demonstrate usage of INNER, FULL, LEFT and RIGHT JOIN.

    Create 2 tables
    create table p1(pid integer, pname varchar(20));
    create table p2(pid integer, ptype varchar(10));
    insert some data into the tables.
    insert into p1(pid, pname) values(1,'p1');
    insert into p1(pid, pname) values(2, 'p2');
    insert into p1(pid, pname) values(4, 'p4');
    insert into p2(pid, ptype) values(1,'t1');
    insert into p2(pid, ptype) values(2, 't2');
    insert into p2(pid, ptype) values(3, 't3');

    select * from p1;

      pid pname
    1 1 p1
    2 2 p2
    3 4 p4


    select * from p2;

      pid ptype
    1 1 t1
    2 2 t2
    3 4 t4

    inner join is implicit. The following two produce the same result.

    select * from p1,p2 where p1.pid=p2.pid;
    select * from p1 inner join p2 on p1.pid=p2.pid;

      pid pname pid ptype
    1 1 p1 1 t1
    2 2 p2 2 t2

    select * from p1 left join p2 on p1.pid=p2.pid;

      pid pname pid ptype
    1 1 p1 1 t1
    2 2 p2 2 t2
    3 4 p4    


     

    1;"p1";1;"t1"
    2;"p2";2;"t2"
    4;"p4";;""
    select * from p1 right join p2 on p1.pid=p2.pid;

      pid pname pid ptype
    1 1 p1 1 t1
    2 2 p2 2 t2
    3     3 t3


    select * from p1 full join p2 on p1.pid=p2.pid;

      pid pname pid ptype
    1 1 p1 1 t1
    2 2 p2 2 t2
    3     3 t3
    4 4 p4    

    CORBA, COM and WebService

    Compare aspects of CORBA and COM

      CORBA COM WebService
    interface IDL IDL WSDL
      Interface Repository typelib WSDL
      POA ClassFactory  
      Active Object Map GIT, ROT  
    Locate the server Implementation Repository;
    IIOP
    Interoperable Object Reference (IOR)
    Registry UDDI
      CORBA::object to string    
      static invocation interface (SII)    
      dynamic invocation interface IDispatch  
      Dynamic Skeleton Interface (DSI)    
    October 19

    regex in eclipse

    QuickREx provides a nice dialog to help user compose regex pattern, but it does not provide “replace” feature. Regex Util provides nice feature to displace “replaced” result, but it does not allow user to copy result into clipboard, just allows user to preview results. Another not so nice fact is that Regex Util uses “$1”, but boost.regex uses “\1” format.

    October 13

    custom deleter and shared_ptr

    Custom deleter can be used to manage resource other than memory via shared_ptr. Here I elaborated some usage of custom deleter.

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <boost/bind.hpp>
    #include <list>
    using namespace std;
    class custom_deleter_demo
    {
    public:
        custom_deleter_demo(int data):m_data(data){    }
        void custom_deleter0()
        {
            std::cout << __FUNCTION__ << " data is " << m_data << std::endl;
            delete this;
        }
        void custom_deleter1(int extra_arg)
        {
            std::cout << __FUNCTION__ << " data is " << m_data <<
            ", extra argument is " << extra_arg << std::endl;
            delete this;
        }
        static void static_custom_deleter(custom_deleter_demo* ptr)
        {
            std::cout << __FUNCTION__ << " data is " << ptr->m_data << std::endl;
            delete ptr;
        }
    private:
        ~custom_deleter_demo()
        {
            std::cout << __FUNCTION__ << " data is " << m_data << std::endl;
        }
        int m_data;
    };

    int main() {
        typedef boost::shared_ptr<custom_deleter_demo> ptr_custom_deleter;
        std::list<ptr_custom_deleter> my_list;
        my_list.push_back(ptr_custom_deleter(new custom_deleter_demo(__LINE__),
                custom_deleter_demo::static_custom_deleter));
        custom_deleter_demo* ptr_object=new custom_deleter_demo(__LINE__);
        my_list.push_back(ptr_custom_deleter(ptr_object,
                boost::bind(&custom_deleter_demo::custom_deleter0, ptr_object)) );
        ptr_object=new custom_deleter_demo(__LINE__);
        my_list.push_back(ptr_custom_deleter(ptr_object,
                boost::bind(&custom_deleter_demo::custom_deleter1, ptr_object,__LINE__)) );
        my_list.clear();
        cout << "Demo custom deleter with shared_ptr" << endl;
        return 0;
    }

    September 30

    build boost_1_40_0.7z via Visual Studio 2008 Profession on Windows XP

    At first I build it in usual way as I did with boost 1.39, but bjam (Boost.Jam 03.1.17) prints a lot of errors like the following.

    cl : Command line error D8022 : cannot open 'bin.v2\libs\math\config\msvc-9.0\debug\link-static\threading-multi\has_long_double_support.obj.rsp'

    The file does exist on my disk. At last I resort to the tool File Monitor in order to find out the root cause. File Monitor captured the following error:

    1:53:37 PM    cl.exe:6324    OPEN    D:\bin.v2\libs\math\build\msvc-9.0\debug\threading-multi\pch.pch.rsp    PATH NOT FOUND    Options: Open  Access: Read   

    It seems that bjam was passing incorrect path to cl.exe. The error is known, and the fix is simple. I created the following batch file and build it successfully. Before starting, I already have d:\boost_1_40_0\bjam.exe in place. size of d:\boost_1_40_0 is 5.56 GB after build completed.

    subst x: D:\boost_1_40_0
    call "%VS90COMNTOOLS%\..\..\vc\bin\vcvars32.bat"
    SET PYTHON_ROOT=C:\Python26
    SET PYTHON_VERSION=2.6
    SET ICU_PATH=D:\opensource\ICU4C-4_2\icu
    cd /d x:\
    .\bjam.exe --without-mpi --toolset=msvc-9.0 stage --build-type=complete

     

    Command line to build single library:

    cd /d D:\opensource\boost\boost_1_40_0\libs\program_options\build
    D:\opensource\boost\bjam.exe "-sTOOLS=msvc" link=static threading=multi
    D:\opensource\boost\bjam.exe "-sTOOLS=msvc" link=static threading=multi variant=release
    D:\opensource\boost\bjam.exe "-sTOOLS=msvc" threading=multi variant=release
    D:\opensource\boost\bjam.exe "-sTOOLS=msvc" threading=multi variant=release

    Command line from "Building Boost with Visual Studio"

    .\bjam --toolset=msvc-9.0 --with-date_time --with-filesystem --with-iostreams -sBZIP2_INCLUDE=C:\bzip2-1.0.5 -sBZIP2_SOURCE=C:\bzip2-1.0.5 -sZLIB_INCLUDE=C:\zlib-1.2.3 -sZLIB_SOURCE=C:\zlib-1.2.3 --with-serialization --with-test --with-thread --build-type=complete stage

    Command line from boost-users@lists.boost.org

    bjam --layout=versioned --toolset=msvc-9.0 variant=debug threading=multi link=static runtime-link=static stage

    September 29

    self debugging on XP

    It is nice to save some useful information at the point of application crash. The useful methods including call stack and minidump file. Call stack can be obtained by installing exception filter via  AddVectoredExceptionHandler Function, stack trace can be obtained via StackWalk64 Function, and minidump file can be created via MiniDumpWriteDump Function.

    WinDbg can open the minidump file. Use .sympath+ <pdb path name> to let WinDBG search this folder before _NT_SYMBOL_PATH. Use .exepath+ command to inform windbg search for executable image file.

    September 25

    ATL, MFC and scoped_any

    I am glad to found Achieve More Reliable Resource Management with Our Custom C++ Classes, but when using it in a unit test project, I got weird compile error. The error points to line 238 of scoped_any.h

    DECLARE_SMART_ANY_TYPEDEFS(scoped) and according to other error message it claims “close_rpc_binding” is not valid. After struggling it turned out to be confliction between ATL and MFC. In an ATL project the source file compiled successfully, but in its corresponding unit test project I have to use MFC because CPPUNIT MFCTestRunner is used to produce GUI. At last the problem was solved by moving MFC related headers from stdafx.h to where they are actually required, and disable precompiled header.

    There is also a post(Automate Resource Management with shared_ptr) demonstrating resource management via custom deleter and boost::shared_ptr.

    September 22

    file transfer over asynchronous TCP connection via boost.asio

    // another sample that send file name and content to Tcp server, but using asynchronous mode Tcp connection

    //
    // send a file to a tcp server via boost.asio library
    #include <iostream>
    #include <boost/asio.hpp>
    #include <boost/bind.hpp>
    #include <fstream>
    #include <sstream>
    using boost::asio::ip::tcp;
    class async_tcp_client
    {
    public:
        async_tcp_client(boost::asio::io_service& io_service,
            const std::string& server, const std::string& path)
            : resolver_(io_service),
            socket_(io_service)
        {
            size_t pos = server.find(':');
            if (pos==std::string::npos)
                return;
            std::string port_string = server.substr(pos+1);
            std::string server_ip_or_host = server.substr(0, pos);

            source_file.open(path.c_str(), std::ios_base::binary | std::ios_base::ate);
            if (!source_file)
            {
                std::cout << "failed to open " << path << std::endl;
                return ;
            }
            size_t file_size = source_file.tellg();
            source_file.seekg(0);
            // first send file name and file size to server
            std::ostream request_stream(&request_);
            request_stream << path << "\n"
                << file_size << "\n\n";
            std::cout << "request size:"<<request_.size()<<std::endl;
            // Start an asynchronous resolve to translate the server and service names
            // into a list of endpoints.
            tcp::resolver::query query(server_ip_or_host, port_string);
            resolver_.async_resolve(query,
                boost::bind(&async_tcp_client::handle_resolve, this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::iterator));
        }

    private:
        void handle_resolve(const boost::system::error_code& err,
            tcp::resolver::iterator endpoint_iterator)
        {
            if (!err)
            {
                // Attempt a connection to the first endpoint in the list. Each endpoint
                // will be tried until we successfully establish a connection.
                tcp::endpoint endpoint = *endpoint_iterator;
                socket_.async_connect(endpoint,
                    boost::bind(&async_tcp_client::handle_connect, this,
                    boost::asio::placeholders::error, ++endpoint_iterator));
            }
            else
            {
                std::cout << "Error: " << err.message() << "\n";
            }
        }

        void handle_connect(const boost::system::error_code& err,
            tcp::resolver::iterator endpoint_iterator)
        {
            if (!err)
            {
                // The connection was successful. Send the request.
                boost::asio::async_write(socket_, request_,
                    boost::bind(&async_tcp_client::handle_write_file, this,
                    boost::asio::placeholders::error));
            }
            else if (endpoint_iterator != tcp::resolver::iterator())
            {
                // The connection failed. Try the next endpoint in the list.
                socket_.close();
                tcp::endpoint endpoint = *endpoint_iterator;
                socket_.async_connect(endpoint,
                    boost::bind(&async_tcp_client::handle_connect, this,
                    boost::asio::placeholders::error, ++endpoint_iterator));
            }
            else
            {
                std::cout << "Error: " << err.message() << "\n";
            }
        }

        void handle_write_file(const boost::system::error_code& err)
        {
            if (!err)
            {
                    if (source_file.eof()==false)
                    {
                        source_file.read(buf.c_array(), (std::streamsize)buf.size());
                        if (source_file.gcount()<=0)
                        {
                            std::cout << "read file error " << std::endl;
                            return;
                        }
                        std::cout << "send " <<source_file.gcount()<<" bytes, total:" << source_file.tellg() << " bytes.\n";
                        boost::asio::async_write(socket_,
                            boost::asio::buffer(buf.c_array(), source_file.gcount()),
                            boost::bind(&async_tcp_client::handle_write_file, this,
                            boost::asio::placeholders::error));
                        if (err)
                        {
                            std::cout << "send error:" << err << std::endl;
                            return;
                        }
                    }
                    else
                        return;
            }
            else
            {
                std::cout << "Error: " << err.message() << "\n";
            }

        }
        tcp::resolver resolver_;
        tcp::socket socket_;
        boost::array<char, 1024> buf;
        boost::asio::streambuf request_;
        std::ifstream source_file;
    };
    int main(int argc, char* argv[])
    {
        if (argc != 3)
        {
            std::cerr << "Usage: " << argv[0] << " <server-address> <file path>" << std::endl;
            std::cerr << "sample: " << argv[0] << " 127.0.0.1:1234 c:\\tmp\\a.txt" << std::endl;
            return __LINE__;
        }
        try
        {
            boost::asio::io_service io_service;
            async_tcp_client client(io_service, argv[1], argv[2]);
            io_service.run();

            std::cout << "send file " << argv[2] << " completed successfully.\n";
    //         system("pause");
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
        return 0;
    }

    // I also made an asynchronous Tcp server to accept work with above client.

    //receive a file from socket client via boost.asio
    #include <iostream>
    #include <string>
    #include <boost/asio.hpp>
    #include <fstream>
    #include <boost/bind.hpp>
    #include <boost/function.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/enable_shared_from_this.hpp>
    unsigned short tcp_port = 1234;
    class async_tcp_connection: public boost::enable_shared_from_this<async_tcp_connection>
    {
    public:
        async_tcp_connection(boost::asio::io_service& io_service)
            : socket_(io_service), file_size(0)
        {
        }
        void start()
        {
            std::cout << __FUNCTION__  << std::endl;
            async_read_until(socket_,
                request_buf, "\n\n",
                boost::bind(&async_tcp_connection::handle_read_request,
                shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
        }
        boost::asio::ip::tcp::socket& socket() { return socket_; }
    private:
        boost::asio::streambuf request_buf;
        size_t file_size;
        std::ofstream output_file;
        boost::asio::ip::tcp::socket socket_;
        boost::array<char, 40960> buf;
        void handle_read_request(const boost::system::error_code& err, std::size_t bytes_transferred)
        {
            if (err)
            {
                return handle_error(__FUNCTION__, err);
            }
            std::cout << __FUNCTION__ << "(" << bytes_transferred << ")"
                << ", in_avail=" << request_buf.in_avail()
                << ", size=" << request_buf.size()
                << ", max_size=" << request_buf.max_size() <<".\n";
            std::istream request_stream(&request_buf);
            std::string file_path;           
            request_stream >> file_path;
            request_stream >> file_size;
            request_stream.read(buf.c_array(), 2); // eat the "\n\n"
            std::cout << file_path << " size is " << file_size << ", tellg=" << request_stream.tellg()<< std::endl;
            size_t pos = file_path.find_last_of('\\');
            if (pos!=std::string::npos)
                file_path = file_path.substr(pos+1);
            output_file.open(file_path.c_str(), std::ios_base::binary);
            if (!output_file)
            {
                std::cout << "failed to open " << file_path << std::endl;
                return;
            }
            // write extra bytes to file
            do
            {
                request_stream.read(buf.c_array(), (std::streamsize)buf.size());
                std::cout << __FUNCTION__ << " write " << request_stream.gcount() << " bytes.\n";
                output_file.write(buf.c_array(), request_stream.gcount());
            } while (request_stream.gcount()>0);
            async_read(socket_, boost::asio::buffer(buf.c_array(), buf.size()),
                boost::bind(&async_tcp_connection::handle_read_file_content,
                shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));          
        }

        void handle_read_file_content(const boost::system::error_code& err, std::size_t bytes_transferred)
        {
            if (bytes_transferred>0)
            {
                output_file.write(buf.c_array(), (std::streamsize)bytes_transferred);
                std::cout << __FUNCTION__ << " recv " << output_file.tellp() << " bytes."<< std::endl;
                if (output_file.tellp()>=(std::streamsize)file_size)
                {
                    return;
                }
            }
            if (err)
            {
                return handle_error(__FUNCTION__, err);
            }
            async_read(socket_, boost::asio::buffer(buf.c_array(), buf.size()),
                boost::bind(&async_tcp_connection::handle_read_file_content,
                shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
        }
        void handle_error(const std::string& function_name, const boost::system::error_code& err)
        {
            std::cout << __FUNCTION__ << " in " << function_name <<" due to " << err <<" " << err.message()<< std::endl;
        }
    };

    class async_tcp_server : private boost::noncopyable
    {
    public:
        typedef boost::shared_ptr<async_tcp_connection> ptr_async_tcp_connection;

        async_tcp_server(unsigned short port)
            : acceptor_(io_service_, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), true)
        {
                ptr_async_tcp_connection new_connection_(new async_tcp_connection(io_service_));
                acceptor_.async_accept(new_connection_->socket(),
                boost::bind(&async_tcp_server::handle_accept, this,new_connection_,
                boost::asio::placeholders::error));
                io_service_.run();
       }   
        void handle_accept(ptr_async_tcp_connection current_connection, const boost::system::error_code& e)
        {
            std::cout << __FUNCTION__ << " " << e << ", " << e.message()<<std::endl;
            if (!e)
            {
                current_connection->start();
                //ptr_async_tcp_connection new_connection_(new async_tcp_connection(io_service_));
                //acceptor_.async_accept(new_connection_->socket(),
                //    boost::bind(&async_tcp_server::handle_accept, this,new_connection_,
                //    boost::asio::placeholders::error));
            }
        }
        ~async_tcp_server()
        {
            io_service_.stop();
        }
    private:
        boost::asio::io_service io_service_;
        boost::asio::ip::tcp::acceptor acceptor_;
    };

    int main(int argc, char* argv[])
    {
        try
        {
            if (argc==2)
            {
                tcp_port=atoi(argv[1]);
            }
            std::cout <<argv[0] << " listen on port " << tcp_port << std::endl;
            async_tcp_server *recv_file_tcp_server = new async_tcp_server(tcp_port);
            delete recv_file_tcp_server;
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
        return 0;
    }

    file transfer over synchronousTCP connection via boost.asio

    //First is a synchronous TCP client that send file name and file content to Tcp Server.

    //
    // send a file to a tcp server via boost.asio library
    #include <iostream>
    #include <boost/asio.hpp>
    #include <fstream>
    #include <sstream>
    using boost::asio::ip::tcp;
    int main(int argc, char* argv[])
    {
        if (argc != 3)
        {
            std::cerr << "Usage: " << argv[0] << " <server-address> <file path>" << std::endl;
            std::cerr << "sample: " << argv[0] << " 127.0.0.1:1234 c:\\tmp\\a.txt" << std::endl;
            return __LINE__;
        }
        try
        {
            std::string server_ip_or_host = argv[1];
            size_t pos = server_ip_or_host.find(':');
            if (pos==std::string::npos)
                return __LINE__;
            std::string port_string = server_ip_or_host.substr(pos+1);
            server_ip_or_host = server_ip_or_host.substr(0, pos);
            boost::asio::io_service io_service;
            tcp::resolver resolver(io_service);
            tcp::resolver::query query(server_ip_or_host, port_string);
            tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
            tcp::resolver::iterator end;
            tcp::socket socket(io_service);
            boost::system::error_code error = boost::asio::error::host_not_found;
            while (error && endpoint_iterator != end)
            {
                socket.close();
                socket.connect(*endpoint_iterator++, error);
            }
            if (error)
                return __LINE__;
            std::cout << "connected to " << argv[1] << std::endl;
            boost::array<char, 1024> buf;
            std::ifstream source_file(argv[2], std::ios_base::binary | std::ios_base::ate);
            if (!source_file)
            {
                std::cout << "failed to open " << argv[2] << std::endl;
                return __LINE__;
            }
            size_t file_size = source_file.tellg();
            source_file.seekg(0);
            // first send file name and file size to server
            boost::asio::streambuf request;
            std::ostream request_stream(&request);
            request_stream << argv[2] << "\n"
                << file_size << "\n\n";
            boost::asio::write(socket, request);
            std::cout << "start sending file content.\n";
            for (;;)
            {

                if (source_file.eof()==false)
                {
                    source_file.read(buf.c_array(), (std::streamsize)buf.size());
                    if (source_file.gcount()<=0)
                    {
                        std::cout << "read file error " << std::endl;
                        return __LINE__;
                    }
                    boost::asio::write(socket, boost::asio::buffer(buf.c_array(),
                        source_file.gcount()),
                        boost::asio::transfer_all(), error);
                    if (error)
                    {
                        std::cout << "send error:" << error << std::endl;
                        return __LINE__;
                    }
                }
                else
                    break;
            }
            std::cout << "send file " << argv[2] << " completed successfully.\n";
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
        return 0;
    }

     

    // next is a Tcp server working in synchronous mode that accept file from above Tcp client. This sample also demonstrate usage of async_read_until(). The trick with async_read_until is that it will read more than I want and those extra bytes must be properly handled.

    //receive a file from socket client via boost.asio
    #include <ctime>
    #include <iostream>
    #include <string>
    #include <boost/asio.hpp>
    #include <fstream>
    #include <sstream>
    unsigned short tcp_port = 1234;

    int main(int argc, char* argv[])
    {
        boost::array<char, 1024> buf;
        size_t file_size = 0;
        try
        {
            if (argc==2)
            {
                tcp_port=atoi(argv[1]);
            }
            std::cout <<argv[0] << " listen on port " << tcp_port << std::endl;
            boost::asio::io_service io_service;
            boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), tcp_port));
            boost::system::error_code error;
            boost::asio::ip::tcp::socket socket(io_service);
            acceptor.accept(socket);
            std::cout << "get client connection." << std::endl;
            boost::asio::streambuf request_buf;
            boost::asio::read_until(socket, request_buf, "\n\n");
            std::cout<< "request size:" << request_buf.size() << "\n";
            std::istream request_stream(&request_buf);
            std::string file_path;           
            request_stream >> file_path;
            request_stream >> file_size;
            request_stream.read(buf.c_array(), 2); // eat the "\n\n"

            std::cout << file_path << " size is " << file_size << std::endl;
            size_t pos = file_path.find_last_of('\\');
            if (pos!=std::string::npos)
                file_path = file_path.substr(pos+1);
            std::ofstream output_file(file_path.c_str(), std::ios_base::binary);
            if (!output_file)
            {
                std::cout << "failed to open " << file_path << std::endl;
                return __LINE__;
            }

            // write extra bytes to file
            do
            {
                request_stream.read(buf.c_array(), (std::streamsize)buf.size());
                std::cout << __FUNCTION__ << " write " << request_stream.gcount() << " bytes.\n";
                output_file.write(buf.c_array(), request_stream.gcount());
            } while (request_stream.gcount()>0);

            for (;;)
            {
                size_t len = socket.read_some(boost::asio::buffer(buf), error);
                if (len>0)
                    output_file.write(buf.c_array(), (std::streamsize)len);
                if (output_file.tellp()== (std::fstream::pos_type)(std::streamsize)file_size)
                    break; // file was received
                if (error)
                {
                    std::cout << error << std::endl;
                    break;
                }
            }
            std::cout << "received " << output_file.tellp() << " bytes.\n";
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
        return 0;
    }

    July 26

    DevPartner 9.02 coverage analysis

    DevPartner failed to instrument two projects with “Error and Coverage” type, the only common fact is that there is a medium size CPP file in thos projects, one is around 40k, another is around 64k. It seems to be bug because those two projects can be instrumented successfully with “Error detection” or “Coverage or performance” type, and the debug configuration is also working, at last a colleague found a workaround with release configuration – disable optimization.

    July 04

    usage of boost::program_options::parse_config_file

    I just need to create options_description as usual, and prepare configuration file in the following format:

    #include <boost/program_options.hpp>
    namespace po = boost::program_options;

    std::stringstream ss;
    ss  << "CurrentX=1234"<<std::endl
        <<"CurrentY=456"<<std::endl;
        po::options_description desc("Allowed options");
        desc.add_options()
            ("help,h", "produce help message")
            ("CurrentX", po::value<int>(), "set CurrentX")
            ("CurrentY", po::value<int>(), "set CurrentY")
            ;

        po::variables_map vm;       
        po::store(po::parse_config_file(ss, desc, true), vm);

    July 02

    Programtically close child console process

    PostThreadMessage(process_info.dwThreadId, WM_QUIT, 0 ,0); does not work; I have to use CREATE_NEW_CONSOLE flag when creating the child process, so GenerateConsoleCtrlEvent does not work either. Console HWND can be found via EnumWindows API, then parent process invoke PostMessage(console_window, WM_CLOSE, 0, 0); or PostMessage(console_window, WM_SYSCOMMAND, SC_CLOSE, 0); child process will receive CTRL_CLOSE_EVENT, so child process can register CtrlHandler via SetConsoleCtrlHandler to close itself gracefully.If child process does not terminate within certain time, windows will prompt up “not respond” window, but child process can still exit when it finished its execution, or parent process can also invoke TerminateProcess to kill child process.

    June 24

    Build wxWidgets 2.8.10 with OpenGL via VC++ 2008

    modify wxWidgets-2.8.10\include\wx\setup_inc.h and
    wxWidgets-2.8.10\include\wx\msw\setup.h to enable wxUSE_GLCANVAS      
    #define wxUSE_GLCANVAS       1

    start VC++ command window and run following command:

    D:\opensource\wxWidgets-2.8.10\build\msw>nmake -f makefile.vc MONOLITHIC=0 SHARED=0 BUILD=release USE_OPENGL=1 USE_ODBC=1 UNICODE=1

    D:\opensource\wxWidgets-2.8.10\build\msw>nmake -f makefile.vc MONOLITHIC=0 SHARED=0 BUILD=debug USE_OPENGL=1 USE_ODBC=1 UNICODE=1

    June 09

    boost::multi_index_container and boost::shared_ptr

    It is a surprise that google only returns 8 results with the following search “multi_index ordered_unique shared_ptr custom key extractor”.

    May 28

    Build boost 1.39 with python 2.6 and ICU4.2 via VC++ 2008

    --build-type=complete option does not work with boost 1.39 (bjam reports error). So I am recording the following commands”

    ECHOE change code page to 1252
    chcp 1252
    rem chcp 1252 can't remove the warning about code page problem
    call "%VS90COMNTOOLS%\..\..\vc\bin\vcvars32.bat"
    SET PYTHON_ROOT=C:\Python26
    SET PYTHON_VERSION=2.6
    SET ICU_PATH=D:\opensource\ICU4C-4_2\icu
    cd /d D:\opensource\boost_1_39_0
    rem D:\opensource\boost_1_39_0\bjam.exe --without-mpi --toolset=msvc-9.0 stage --build-type=complete
    D:\opensource\boost_1_39_0\bjam.exe --without-mpi --toolset=msvc-9.0 debug release threading=multi
    D:\opensource\boost_1_39_0\bjam.exe --without-mpi --toolset=msvc-9.0 debug release threading=multi link=shared

    May 16

    Singapore Visa

    第一次跑过去,被门口的工作人员拦住问有没有带户口本原件,而且要求全本。我说有同事办过不需要这些东西,给出的答复是上面传达的精神,天天不同的。过了一个礼拜再过去,户口本带上了,结果根本就没有用上,检查材料的时候没有要求看身份证或户口本原件,不过回来后据同事说有的人被要求出示身份证。原来领事馆离娄山关路地铁2号口近,万山路靠近娄山关路。