Skip to main content

Featured

Build docker image from multiple build contexts

Build docker image from multiple build contexts Building a docker image requires specifying a source of truth to include in the image from a local directory or a remote git repository. In the previous version, the docker BuildKit allows users to specify the build context from a single source of truth only. However, the engineers may need to have the context from different locations based on the type of files. For instance, icons, images or other resources that are not included in the same package, including the resource from other docker images. Fortunately, the Docker Buildx toolkit supports multiple build context flag for Docker 1.4. Let's learn how to use this new feature. The following list is a shortcut for jumping into a specific topic handy. What version of Docker is this tutorial targeting? How to specify the version of Dockerfile frontend? Ho

[C++]傳遞Class Member function pointer至其他Class

困擾已久的傳遞Class的Member function到其他class的問題,在今天仔細參詳了半天高手的code以後,終於把之前的疑惑解決了。

原本都知道要用第三個class來處理這問題,但由於一直搞不懂第三個要怎麼做,所以就一直寫不出來。

目前參考的方法是使用一個Base class來當做傳遞Function pointer的介面,然後一個Template class來讓內層使用的class來使用function pointer,也避開兩個互相參照的class的交互參照之問題。

處理方式如下:
Class Processer (底下稱CP)有工作要麻煩 Class Thread (底下稱CT)處理,但是為了讓Main thread不要卡住,所以CT是另外開一個Thread來處理CP要求的工作。
然而當CT在處理工作時如遇到了例外,並無法立即讓CP知道目前的狀況,所以就需要讓CP開個管道(Function Pointer)來讓CT可以在遇到問題時,回來告知CP。

原本是打算用PostMessage()來達成這樣的需求,但是CT所在的dll可能會移植到別的平台上,所以如果使用PostMessage()來做的話,那麼在移植上,還需要去針對不同平台處理。

但是此時的需求只是要把CT遇到的狀況告知給CP,並由CP來告知使用者而已,所以不會造成CT的程序block,所以這邊就採用Class的 callback方式處理。(如果會發生blocking的話,那還是只能用Windows Message的方式處理會比較好處理,不然Thread也是可以。)

底下範例使用
Class CallBackBase:
class CCallBackBase
{
    public:
        CCallBackBase(){};
        ~CCallBackBase(){};

        virtual bool Execute(void *Param) const = 0;
};




Template Class:
template < class cTarClass >
class CTestCallBack : public CCallBackBase
{
    public:
        typedef bool (cTarClass::*LPFUNC)(void *Param);

    protected:
        cTarClass *m_pTarClass;
        LPFUNC m_pTarFunc;

    public:
        CTestCallBack() {
            m_pTarClass = NULL;
        };
        ~CTestCallBack() {};

        void SetCallBack(cTarClass *cTarClassPtr, LPFUNC pFuncPtr){
            m_pTarClass = cTarClassPtr;
            m_pTarFunc = pFuncPtr;
        };

        virtual bool Execute(void *Param) const        //Execute的參數要與function pointer一致是因為操作者是使用此介面來使用function pointer
        {
            if (m_pTarClass)
            {
                return (m_pTarClass->*m_pTarFunc)(Param);
            }else{
                ::printf("ERROR: The call back funciton is not set!!");
            }
            return false;
        };
};


Class Thread:
class CProcessThread
{
    protected:    
        CCallBackBase *m_pCallBack;
        HANDLE m_hThread;

    public:
        CProcessThread(){
            m_pCallBack = NULL;
            m_hThread = NULL;
        };

        ~CProcessThread(){
            if ( m_hThread != NULL )    {
                DWORD dwExitCode = 0;
                ::TerminateThread(this->m_hThread, dwExitCode);

                HANDLE hThread = this->m_hThread;
                this->m_hThread = NULL;
                ::CloseHandle(hThread);
            }
        };

        void StartProcessThread(void)
        {
            this->m_hThread = CreateThread( NULL, 0, ProcessThread, (LPVOID)this, 0, NULL);
        };

        void SetCallBack(CCallBackBase *pCallBack){
            m_pCallBack = pCallBack;
        };

    protected:
        static DWORD WINAPI ProcessThread(LPVOID lpParam)
        {
            CProcessThread *pcmxProcessThread = (CProcessThread*) lpParam;

            return pcmxProcessThread->ProcessFunc();
        };

        DWORD ProcessFunc(void)
        {
            //Set callback data to upper class
            m_pCallBack->Execute((void*) "This message is pass from ProcessThread::ProcessFunc() in Thread!!\n");

            if ( m_hThread != NULL )    {
                DWORD dwExitCode = 0;
                ::TerminateThread(this->m_hThread, dwExitCode);

                HANDLE hThread = this->m_hThread;
                this->m_hThread = NULL;
                
                ::CloseHandle(hThread);
            }

            return 0;
        };
};



Class Process:
class CProcess
{
    protected:
        CTestCallBack<CProcess> m_CallBack;
        CProcessThread m_ProcessThread;

    public:
        CProcess() {
            m_CallBack.SetCallBack(this, &CProcess::CallBackShower);
            m_ProcessThread.SetCallBack(&m_CallBack);
        };
        ~CProcess() {};

        void StartProcess(void)
        {
            m_ProcessThread.StartProcessThread();
        };

        bool CallBackShower(void *Param)
        {
            char szMsg[512];
            strcpy(szMsg, (char*)Param);

            ::printf("The Pass message from call back is \nMsg = %s", szMsg);

            return true;
        };

};



Main program:
int _tmain(int argc, char* argv[])
{
    CProcess Process;

    Process.StartProcess();

    system("pause");
    return 0;
}


執行結果:



程式碼亂跑的問題再另外找解@@

Comments

Popular Posts