2011年2月21日 星期一

[Distributed Algorithms] 第一堂: Introduction

這門課是偏理論的課,原本以為會跟實作相關,像是講解 Java RMI 之類的課。
老師說基本上都是定義與證明。 也好,最近都在寫 code 很少碰理論的東西了。

使用的教科書:  MIT 教授寫的,相當學院派
Distributed algorithms, by Nancy Lynch, Morgan Kaufmann, 1996
首先說明與平行演算法的不同,基本上平行演算法的環境比較確定,向分散式演算法就不能假設 processes 的差異。


再來畫了一個樹狀圖說明演算法證明的分類。


   
  老師舉了清大夜市的紅綠燈管理系統
  safety:不會出車禍
  progress: 保值車輛流通
  
  safety 與 progress 在以後的證明風格會差很多。




因為是第一堂課,所以也就僅止於介紹,老師舉了一些很有趣的例子


1. Muddy Children forehead  (google 面試的考題)
2. 莊子的子非魚
3. Coordinated Attack Program
4. 村莊裡的大屠殺


1和4是哲學的思辨,重點在 Know 這個字
3 是 Jim Gray (Turing Award的得主,釣魚的時候失蹤)


下堂課會開始講 OS 的 Mutual Exclusion Algorithm 
應該會理論到不行


舒服!

2011年2月18日 星期五

Property Lists

從 bundle 中讀取 plist 範例:


- (void)viewDidLoad {
   NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];
   NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
   [dict release];
}

Property Lists

從 bundle 中讀取 plist 範例:

- (void)viewDidLoad {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];
    NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
    [dict release]; 
}


=

iPhone 快速鍵


主要是以寫 iPhone 用到的快速鍵為主:
Command 鍵圖像(Control 鍵):幾種 Apple 鍵盤的這個鍵還同時印有 Apple 標誌(蘋果標誌
Control 鍵圖像(Control 鍵)
Option 或 Alt 鍵圖像(Option 鍵)::這個按鍵還可能印有“Alt”
Shift 圖像(Shift 鍵)
大寫鎖定鍵圖像(Caps Lock):切換大寫鎖定開關
fn(功能鍵) 
Xcode 快速鍵
Shift 圖像Command 鍵圖像E將 detail Pane 隱藏
Command 鍵圖像Rcompile and run
Shift 圖像Command 鍵圖像J
refactoring




好用的




Command 鍵圖像+shift+4
print screen
fn+shift+F11
顯示桌面




好用的



Finder 鍵盤快速鍵
Command-A選擇前端 Finder 視窗中的所有項目(如果沒有開啟中視窗則是桌面)
Option-Command-A取消選取所有項目。
Shift-Command-A開啟“應用程式”檔案夾
Command-C拷貝選取項目/文字至剪貼板
Shift-Command-C開啟“電腦”視窗
Command-D複製選取項目
Shift-Command-D開啟桌面檔案夾
Command-E退出
Command-F尋找任何相符的 Spotlight 屬性
Shift-Command-F尋找 Spotlight 檔案名稱符合項目
Option-Command-F移動到已經開啟的 Spotlight 視窗中的搜尋欄位
Shift-Command-G前往檔案夾
Shift-Command-H開啟目前登入使用者帳號的個人專屬檔案夾
Command-I簡介
Option-Command-I顯示檢閱器
Control-Command-I取得摘要簡介
Shift-Command-I開啟 iDisk
Command-J開啟顯示方式選項
Command-K連接伺服器
Shift-Command-K開啟“網路”視窗
Command-L製作所選項目的替身
Command-M視窗最小化
Option-Command-M將全部視窗縮到最小
Command-N新增 Finder 視窗
Shift-Command-N新增檔案夾
Option-Command-N新增智慧型檔案夾
Command-O開啟選取項目
Shift-Command-Q登出
Option-Shift-Command-Q立即登出
Command-R顯示替身的原項目
Command-T加到側邊欄裡
Shift-Command-T加到喜好項目
Option-Command-T在“Finder”視窗中隱藏工具列 / 顯示工具列
Shift-Command-U開啟“工具程式”檔案夾
Command-V貼上
Command-W關閉視窗
Option-Command-W關閉所有視窗
Command-X剪下
Option-Command-Y幻燈片秀(Mac OS X 10.5 或以上版本)
Command-Z還原/重作
Command-1以圖像顯示
Command-2依列表顯示
Command-3依欄位顯示
Command-4依 Cover Flow 顯示(Mac OS X 10.5 或以上版本)
Command-,(Command 和逗號鍵)開啟 Finder 偏好設定
Command-`(次重音符號鍵,在美式英文鍵盤佈局的 Tab 鍵上方)循環檢視開啟中的“Finder”視窗
Command-Shift-?開啟 Mac 輔助說明
Option-Shift-Command-Esc(按住三秒)- 僅限 Mac OS X v10.5、v10.6 或以上版本強制結束最前面的應用程式
Command-[返回
Command-]往前
Command-向上鍵開啟所含的檔案夾
Control-Command-向上鍵以新視窗開啟所含的檔案夾
Command-向下鍵開啟反白項目
Command-Tab切換應用程式:向前循環
Shift-Command-Tab切換應用程式:向後循環
Command-Delete丟到垃圾桶
Shift-Command-Delete清空垃圾桶
Option-Shift-Command-Delete不顯示確認對話框便直接清空垃圾桶
空白鍵(或 Command-Y)快速查看(Mac OS X 10.5 或以上版本)
按住 Command 鍵同時拖移把拖移的項目移動到其他卷宗/位置(按住本鍵時游標圖像會改變,請參閱這篇文章
按住 Option 鍵同時拖移拷貝拖移的項目(按住本鍵時游標圖像會改變,請參閱這篇文章
按住 Option-Command 組合鍵同時拖移製作拖移項目的替身(按住本鍵時游標圖像會改變,請參閱這篇文章



增加欄位的 html 語法

<tr style="background-color: white; font-size: 10px;"><td style="border-bottom-color: rgb(161, 165, 169); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(161, 165, 169); border-right-style: solid; border-right-width: 1px; font-size: 10px; padding-bottom: 4px; padding-left: 4px; padding-right: 4px; padding-top: 4px;"><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="border-collapse: separate;">
</span></div>
</td><td style="border-bottom-color: rgb(161, 165, 169); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(161, 165, 169); border-right-style: solid; border-right-width: 1px; font-size: 10px; padding-bottom: 4px; padding-left: 4px; padding-right: 4px; padding-top: 4px;"><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">

</div>
</td></tr>

2011年2月16日 星期三

hello bjam

目前決定用 Sqlite++ 來當我字典的資料庫,Sqlite++編譯時需要用到 boost.build tool 來編譯。
試了一陣子結果不行,決定研究一下 bjam 的編譯環境。

編譯 hello world

官方的說明文件:
http://www.boost.org/doc/tools/build/doc/html/index.html

electronic-blue's blog (寫的很好,很容易上手)
http://electronic-blue.wikidot.com/doc:bjam-quickstart

編譯時一開始我弄不清楚 Jamroot 和 Jamfile 的關西
看了electronic-blue 的說明後就成了~!!

2011年2月15日 星期二

聊天室 - based Command Tool

需求:

client:    傳送一個 message   ("filename","varname")
server:   將 filename 檔案內的 varname 的數值減一,減到零時回傳 YES, 否則回傳 NO

eq.  hello.txt
==================
fab = 100
Oxford = 99
==================

client 傳送 ("hello.txt","Oxford"),server便會將Oxford的值減一 => 98。

這樣的程式,可以用網路 http REST 來做,或是包成網路 API Service 來做(這我不會)
但這種簡單的需求,用 socket 就綽綽有餘了。

寫 socket 程式就需要自己定義 protocol,貪圖方便,我就拿了 boost/asio 的聊天室範例程式來修改 (chat):
http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/examples.html
以下是其 protocol: |size|string|

class chat_message
{
public:
  enum { header_length = 4 };
  enum { max_body_length = 512 };

  chat_message()
    : body_length_(0)
  {
  }

  const char* data() const
  {
    return data_;
  }

  char* data()
  {
    return data_;
  }

  size_t length() const
  {
    return header_length + body_length_;
  }

  const char* body() const
  {
    return data_ + header_length;
  }

  char* body()
  {
    return data_ + header_length;
  }

  size_t body_length() const
  {
    return body_length_;
  }

  void body_length(size_t length)
  {
    body_length_ = length;
    if (body_length_ > max_body_length)
      body_length_ = max_body_length;
  }

  bool decode_header()
  {
    using namespace std; // For strncat and atoi.
    char header[header_length + 1] = "";
    strncat(header, data_, header_length);
    body_length_ = atoi(header);
    if (body_length_ > max_body_length)
    {
      body_length_ = 0;
      return false;
    }
    return true;
  }

  void encode_header()
  {
    using namespace std; // For sprintf and memcpy.
    char header[header_length + 1] = "";
    sprintf(header, "%4d", body_length_);
    memcpy(data_, header, header_length);
  }

private:
  char data_[header_length + max_body_length];
  size_t body_length_;
};

既然,protocol 都用此範例了,client & server 當然也用這個範例修改了。

比較麻煩的是,這個範例程式 client & server 都是非同步的方式,非同步在 server 是沒甚麼問題,但 client 使用非同步會很麻煩。需要再 while 迴圈前 Sleep 一秒左右,讓 ioservice 建立連線。
Note:
因為實際使用時,是把 while 中的使用者輸入 cin.getline 部分改成,用參數傳遞的 string,while 迴圈也要拿掉,因此若是非同步的方式,程式馬上就到 c.close(),修改這段程式花了我很大的時間除錯 = ="

boost::asio::io_service io_service;

    tcp::resolver resolver(io_service);
    tcp::resolver::query query(argv[1], argv[2]);
    tcp::resolver::iterator iterator = resolver.resolve(query);

    chat_client c(io_service, iterator);

    boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));

    char line[chat_message::max_body_length + 1];
    while (std::cin.getline(line, chat_message::max_body_length + 1))
    {
      using namespace std; // For strlen and memcpy.
      chat_message msg;
      msg.body_length(strlen(line));
      memcpy(msg.body(), line, msg.body_length());
      msg.encode_header();
      c.write(msg);
    }

    c.close();
    t.join();

因此我將 client 程式改成同步的方式來執行 (舒服)

boost::asio::io_service io_service;

        tcp::resolver resolver(io_service);
        tcp::resolver::query query(argv[1], argv[2]);
        tcp::resolver::iterator iterator = resolver.resolve(query);
        tcp::resolver::iterator end;

        tcp::socket s(io_service);
        boost::system::error_code error = boost::asio::error::host_not_found;
        while (error && iterator != end)
        {
            s.close();
            s.connect(*iterator++, error);
        }
        if (error)
            throw boost::system::system_error(error);

        char line[chat_message::max_body_length + 1];
        strcpy(line,"hello.txt Seg ");
        chat_message write_msgs_;
        write_msgs_.body_length(strlen(line));
        memcpy(write_msgs_.body(), line, write_msgs_.body_length());
        write_msgs_.encode_header();

        boost::asio::write(s, 
            boost::asio::buffer(write_msgs_.data(), write_msgs_.length()));

        chat_message read_msg_;
        //boost::asio::read(sread_msg_.body(), read_msg_.body_length()),
        
        size_t reply_length_header = boost::asio::read(s,
            boost::asio::buffer(read_msg_.data(), chat_message::header_length));
        std::cout << "reply_length_header = " << reply_length_header << std::endl;

        read_msg_.decode_header();

        size_t reply_length_body = boost::asio::read(s,
            boost::asio::buffer(read_msg_.body(), read_msg_.body_length()));

        std::cout << read_msg_.body() << std::endl;

        s.close();

等待時間的問題解決了,接下來要包成 library。

包成 static library 還有些 issue

1. boost library 的 BOOST_ALL_NO_LIB 問題:
我包成 foo.lib 給 test.exe 用但在編譯的時候 linker 竟然還會有問題
LINK : fatal error LNK1104: cannot open file 'libboost_thread-vc100-mt-1_45.lib'
參考下文:
http://stackoverflow.com/questions/4736877/how-to-link-boost-in-a-dependant-static-library

2. VS2010 的 Static Library 無法給 VC6 用


於是我就包成 DLL 的版本
修改下面的 code 包成的 (用 vs2010 建立的 dll wizard 我包失敗 = =)
http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855

於是我的情人節就給了這支程式了! e04!!