2013年9月15日 星期日

if __name__ == "__main__"

在 python 裡 __name__ 可用來識別當下所執行 module 名稱
讓我們來看以下幾個範例

# file: test1.py
print "the module name is:", __name__


#file: test2.py
print "the module name is:", __name__


#file: test3.py
import test1
import test2
print "the module name is:", __name__

分別執行 test1.py test2.py test3.py 可到如下結果


#>: python test1.py
the module name is: __main__

#>: python test2.py
the module name is: __main__

#>: python test3.py
the module name is: test1
the module name is: test2
the module name is: __main__

我們可以知道,在當下執行的檔案 __name__ 會是 "__main__",若被 import 到其他檔案中被執行到則 __name__ 會是該 module 的名稱,可由執行 test3.py 驗證.

由於 python 是直譯是語言,interpreter 再載入各 module 時同時也會直行該 module 所包含的程式碼.若要避免不必要地誤動作可在各 module 內加入 if __name__ == "__main__",避免程式碼被執行.

我們可將上述檔案改變如下,並觀察執行結果,則可發現在執行 test3.py 的時候可避開 test1.py
與  test2.py 載入時不必要的執行.

# file: test1.py
if __name__ == "__main__":
    print "the module name is:", __name__


#file: test2.py
if __name__ == "__main__":
    print "the module name is:", __name__


#file: test3.py
import test1
import test2

if __name__ == "__main__":
    print "the module name is:", __name__

#>: python test1.py:
the module name is: __main__

#>: python test2.py
the module name is: __main__

#>: python test3.py
the module name is: __main__

2013年9月14日 星期六

Mplayer backend example





#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <string>


using namespace std;

int main()
{
        int   pipefd[2] = {0};

        if(pipe(pipefd) != 0) {
                printf("pipe open failed\n");
        }

        if(fork() != 0) {
                string command;
                close(pipefd[0]);

                while(1) {
                        cout << "command:";
                        cin >> command;
                        command += "\n";

                        write(pipefd[1], command.c_str(), command.length());

                }
        } else {
                dup2(pipefd[0], fileno(stdin));

                execl("/usr/bin/mplayer", "mplayer",
                      "-slave", "-fs", "-osdlevel", "0", "-really-quiet",
                      "-input", "nodefault-bindings", "-noconfig", "all",
                      "/home/archer/Videos/300_Trailer2_8mbps_1080p29.98_5.1.wmv", NULL);
        }

        return 0;
}

2013年9月13日 星期五

Observer Model example for C++


  • Observer Model
    • The Observer dose not actively to get the data from the Subject else the Subject will
      notify the Observer when there are something changed.
    • 觀察者模式定義了物件之間一對多的關係
    • 主題(Subject) 更新觀察者的方式 ,是透過一個共用介面。
    • 觀察者與可觀察者之間採用鬆綁的方式結合(loose-coupling),因為可觀察者不知道觀察者的細節,只知道觀察者有實踐特定的觀察者介面。




#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <list>

using namespace std;

class CObserver
{
public:
        virtual void update(int data) = 0;
};

class CSubject
{
public:
        virtual void registerObserver(CObserver *obs) = 0;
        virtual void deleteObserver(CObserver *obs) = 0;
        virtual void notify(void) = 0;
};

class CInformationStation : public CSubject
{
private:
        list<CObserver *> m_observerList;
public:
        virtual void registerObserver(CObserver *obs);
        virtual void deleteObserver(CObserver *obs);
        virtual void notify(void);
};

void CInformationStation::registerObserver(CObserver *obs)
{
        list<CObserver *>::iterator it;
        bool found = false;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                if(*it == obs){
                        found = true;
                        break;
                }
        }

        if(!found)
                m_observerList.push_back(obs);
}

void CInformationStation::deleteObserver(CObserver *obs)
{
        list<CObserver *>::iterator it;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                if(*it == obs) {
                        m_observerList.erase(it);
                        break;
                }
        }
}

void CInformationStation::notify(void)
{
        list<CObserver *>::iterator it;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                srand((int)time(0));
                sleep(1);
                (*it)->update( rand() % 1000);
        }
}

class CStatistic : public CObserver
{
private:
        int m_data;
public:
        CStatistic() : m_data(0) {}

        virtual void update(int data)
        {
                m_data = data;
        }

        void display(void)
        {
                printf("[%s] m_data:%d\n", __PRETTY_FUNCTION__, m_data);
        }
};

int main()
{
        CInformationStation station;
        CStatistic statistic1, statistic2, statistic3;

        station.registerObserver(&statistic1);
        station.registerObserver(&statistic2);
        station.registerObserver(&statistic3);

        station.notify();

        statistic1.display();
        statistic2.display();
        statistic3.display();

        return 0;
}

2013年9月12日 星期四

Call by reference of const object argument passing.

當 function 或 member 透過 call by reference 傳遞參數時有個有趣的現象,如下範例

#include <stdlib.h>
#include <stdio.h>
#include <string>

using namespace std;

class CFoo
{
public:
    CFoo(strring &str)
    {
        printf("[%s]: str:%p\n", __PRETTY_FUNCTION__, &str);
    }

    CFoo(int &i)
    {
        printf("[%s]: i:%p\n", __PRETTY_FUNCTION__, &i);
    }
    CFoo(CFoo &foo)
    {
        printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
    }
    ~CFoo()
    {
       printf("[%s]\n", __PRETTY_FUNCTION__);
    }
};

void func1(const CFoo &foo)
{
    printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
}

//void func2(CFoo &foo)
//{
//    printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
//}

int main()
{
    CFoo foo;
    string str = "str";
    int i = 10;

    printf("&foo:%p\n", &foo);
    func1(foo);

    printf("&str:%p\n", &str);
    func1(str);

    printf("&i:%p\n", & i);
    func1(i);

    return 0;
}

當 g++ 面對不同型態的參數呼叫 func1() 時 , 除了 func1(foo) 之外, 都會暫時產生一個 CFoo 的object 並依照其 CFoo 所定義的 constructor 完成 func1 參數裡的物件建構.但只限 const object.

如果將 func1() 替換成 func2(),則除了 func2(foo) 可順利編譯成功, 其他方式的呼叫皆會在 compiling time 時出現錯誤.因為 compiler 並不會為其他呼叫方式產生臨時的 instance, 所以將會有型別不符的錯誤.

void func1(const CFoo &foo)void func2(CFoo &foo) 除了 const 修飾詞所表示的不可修改之外,在參數傳遞的建構方式也有所不同.



2013年9月9日 星期一

Designed Patterns


  • 模式不是程式碼,而是針對特定系統的解決方案,是解決程式中設計的問題。
  • 模式不是被發明,而是被發現。
  • 我門通常把系統中,會變動的部分抽出來封裝。
  • 利用繼承設計次類別的行為,是在編譯時期靜態決定的,而且所以次類別都會繼承到相同的行為。
  • 利用合成的作法擴充物件的行為,就可以在執行時期動態地進行擴充。

(Head First Design Patterns) Strategy Patten


  • 多用合成 ,少用繼承 (More composition less inheritance)
    • 使用合成建立系統具有很大的彈性,不僅可以將演算法封裝成類別,更可以在執行期動態改變行為,只要合成的行為物件,符合特定的介面標準即可。
E.X:

#include <stdlib.h>
#include <stdio.h>

// particular interface
class IFlyBehavior
{
public:
        virtual void fly(void) = 0;
};

// The interface implementance 
class CFlyWithWings : public IFlyBehavior
{
public:
        virtual void fly(void)
        {
                printf("I'm flying\n");
        }
};

// The interface implementance 
class CFlyNoWay : public IFlyBehavior
{
public:
        virtual void fly(void)
        {
                printf("I can't fly\n");
        }
};

// particular interface
class IQuackBehavior
{
public:
        virtual void quack(void) = 0;
};

// The interface implementance 
class CQuack : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("Quick\n");
        }
};

// The interface implementance 
class CMuteQuack : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("<<silence>>\n");
        }
};

class Squeak : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("Squeak\n");
        }
};

class CDuck
{
protected:
        IFlyBehavior *m_flyBehavior;             // more fixable
        IQuackBehavior *m_quackBehavior;  // more fixable
public:
        CDuck(){}
        virtual ~CDuck(){}
        virtual void display() = 0;

        virtual void performQuack(void)
        {
                m_quackBehavior->quack();
        }

        virtual void performFly(void)
        {
                m_flyBehavior->fly();
        }

        virtual void swim()
        {
                printf("All duck float, even decoys!");
        }
};

class CMallardDuck : public CDuck
{
public:
        CMallardDuck()
        {
                m_flyBehavior = new CFlyWithWings(); // can be replacement at runtime
                m_quackBehavior = new CQuack();        
        }
        virtual ~CMallardDuck()
        {
                delete m_flyBehavior;
                delete m_quackBehavior;
        }

        virtual void display(void)
        {
        }
};

int main()
{
        CDuck &mallard =  *(new CMallardDuck());

        mallard.performQuack();
        mallard.performFly();

        return 0;
}

2013年8月27日 星期二

MAC PHY MII GMII RGMII


OSI Network Stack




ETHERNET 的接口實質是 MAC 通過 MII 匯流排控制 PHY 的過程。


MAC
  • MAC是Media Access Control 的縮寫,即媒體訪問控制子層協議。該協議位於OSI七層協議中數據鏈路層的下半部分,主要負責控制與連接物理層的物理介質。在發送數據的時候,MAC協議可以事先判斷是否可以發送數據,如果可以發送將給數據加上一些控制信息,最終將數據以及控制信息以規定的格式發送到物理層;在接收數據的時候,MAC協議首先判斷輸入的信息並是否發生傳輸錯誤,如果沒有錯誤,則去掉控制信息發送至LLC層。以太網MAC由IEEE-802.3以太網標準定義。 
MII  GMII  RGMII

  • 基本上,這三個的作用是一樣的,同樣都是連結MAC層和PHY層的介面。區別在於編碼、速度、使用的腳位數、I/O clock的頻率不同。


  • MII : 這是IEEE 802.3u制定出來,應用在Fast Ethernet上,連接 Data Link Layer 中的MAC層和Physical Layer 中的PHY層(這樣的說法有點瑕疵,因為Data Link Layer有分為MAC層和LLC層,但Physical Layer沒有分其它的層別,統稱為PHY層)的溝通介面。全名為(Media Independent Interface)。


  • MII即媒體獨立接口, 「媒體獨立」表明在不對MAC硬件重新設計或替換的情況下,任何類型的PHY設備都可以正常工作。包括分別用於發送器和接收器的兩條 MII使用8B/10B之編碼,所以它運作在125Mbps的時候,可以傳送包含檔頭的100Mbps的資料。(想成有八條水管,同時有125Mbps的資料流進來,通過了一個閘道,要流到十條水管裡去,這十條水管的平均流速就是125Mbps*8/10=100Mbps。)


  •  IC對PHY做讀寫的時候用一組訊號:MDC(Management Data Control)與MDIO(Management Data Input/Output)。


          輸出和輸入各有四個bit的匯流排:Tx[0:3]、Rx[0:3] (輸出是指IC到PHY、輸入是指PHY到IC)

          MII對於Data sampling reference用的兩組clock,頻率為25MHZ,這兩個訊號為Tx_CLK和Rx_CLK。(Ethernet頻率為2.5MHz)

          通知對方準備輸入資料的輸出和輸入的啟動訊號為:Tx_EN、Rx_EN

          輸出、輸入訊號的錯誤通知訊號為:Tx_ER、Rx_ER

          得到有效輸入資料的通知訊號為:Rx_DV

          網路上出現擁塞的Colision訊號為:Col

          作為carrier回覆用的訊號為:CRS (請參考CSMA/CD)

          MII實作的電路電壓可用+5V或是+3.3V


  • GMII:Gigabit Media Independent Interface,可支援到1Gbps,不同於MII,輸出和輸入各有8個bit。

          Tx:GTXCLK、TxCLK、TxD[0:7]、TxEN、TxER

          Rx:RxCLK、RxD[0:7]、RxDV、RxER、COL、CRS

          MDC、MDIO


  • RGMII:Reduced Gigabit Media Independent Interface,顧名思義就是GMII的縮小版(因為減少了PIN腳位數)啦。

          和GMII一樣可以支援10/100/1000Mbps,只有定義12個訊號,比GMII還少一半:RxC、RxD[0:3]、Rx_CTL、TxC、TxD[0:3]、Tx_CTL

  •  IC控制訊號一樣是透過MDC、MDIO


PHY

  • PHY是物理接口收發器,它實現物理層。包括MII/GMII(介質獨立接口)子層、PCS(物理編碼子層)、PMA(物理介質附加)子層、PMD(物理介質相關)子層、MDI子層。

Reference:
http://blog.csdn.net/dark_goldz/article/details/4691773
http://blog.csdn.net/sahusoft/article/details/6908753