• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Error

            C++博客 首頁 新隨筆 聯系 聚合 管理
              217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks

            #

            M{D%1Y@56QFN6COBX(@Y6BR

            posted @ 2013-03-11 15:58 Enic 閱讀(142) | 評論 (0)編輯 收藏

            // learn_boost_asio.cpp : 定義控制臺應用程序的入口點。
            //
            #include "stdafx.h"
            #include <iostream>
            #include <algorithm>
            #include <memory>
            #include <boost/asio.hpp>
            #include <boost/timer.hpp>
            #include <boost/lambda/lambda.hpp>
            #include <boost/function.hpp>
            #include <boost/bind.hpp>
            namespace asio = boost::asio;
            namespace posix_time = boost::posix_time ;
            // 1.同步定時器使用
            void LeanrHowToUseSynchronouslyTimer()
            {
            asio::io_service io;
            asio::deadline_timer deadLineTimer(io, posix_time::seconds(3));
            boost::timer timerTestDeadLineTimer;
            timerTestDeadLineTimer.restart();
            deadLineTimer.wait();
            double dTime = timerTestDeadLineTimer.elapsed();
            std::cout << dTime << std::endl;
            }
            ////////~
            // 2.異步定時器使用
            class CSomeObject
            {
            public:
            CSomeObject(asio::io_service& ioService) :
               m_deadLineTimer(ioService)
            {
            }
            public:
            void Test()
            {
            m_deadLineTimer.expires_from_now(boost::posix_time::seconds(3));
            m_timerTestDeadTimer.restart();
            m_deadLineTimer.async_wait(
            boost::bind(&CSomeObject::TimerHandler, this, asio::placeholders::error));
            }
            public:
            void TimerHandler(const boost::system::error_code&)
            {
            double dTime = m_timerTestDeadTimer.elapsed();
            std::cout << "time passed: " << dTime << std::endl;
            }
            private:
            boost::timer m_timerTestDeadTimer;
            asio::deadline_timer m_deadLineTimer;
            };
            void LearnHowToUseAsynchronouslyTimer()
            {
            asio::io_service ioService;
            CSomeObject obj(ioService);
            obj.Test();
            asio::io_service::work* pWork = new asio::io_service::work(ioService);
            std::auto_ptr<asio::io_service::work> spWork(pWork);
            ioService.run();
            //spWork.reset(); // Allow run() to exit. 
            }
            //////////////////////////////////////////
            int _tmain(int argc, _TCHAR* argv[])
            {
            LearnHowToUseAsynchronouslyTimer();
            return 0;
            }
            posted @ 2013-03-08 18:04 Enic 閱讀(790) | 評論 (0)編輯 收藏

            從GameDemo.cpp看起

             

            1回顧通常的sdk窗口程序流程:注冊窗口-創建窗口-顯示窗口-啟動消息循環

             

            1.1注冊窗口類

            Duilib中最平凡的真實窗口類是:CWindowWnd,關于窗口注冊提供了兩個函數,嚴格的說應該是幾個:

            RegisterWindowClass()

            RegisterSuperclass()

            GetWindowClassName()

            GetSuperClassName()

            GetClassStyle()

            在我的理解中,后面兩個虛函數的意義應該是:上面這些接口分兩組,一組是用于正常注冊使用,一組用于擴展。

            使用的時候用自定義的窗口對象從CWindowWnd繼承下來,然后定制自己需要的window class

            1.2創建窗口

                CGameFrameWnd* pFrame = new CGameFrameWnd();
                if( pFrame == NULL ) return 0;
                pFrame->Create(NULL, _T(""), UI_WNDSTYLE_FRAME, 0L, 0, 0, 1024, 738);
            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

            CWindowWnd帶有mfc CWnd類似的Create接口用于創建窗口,同事注冊窗口類也通過虛函數的方式延后到子類實現,super機制(如果有super優先注冊)也帶進來。

                if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
                if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;
            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

            1.3顯示窗口

            和sdk是一樣的

            ::ShowWindow(*pFrame, SW_SHOWMAXIMIZED);

            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 1.4消息循環

            CPaintManagerUI::MessageLoop();
            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

            1.5消息回調函數

            在窗口類注冊的時候應該要注冊窗口回調函數指針,Duilib中默認是在CWindowWnd::RegisterWindow注冊:

            bool CWindowWnd::RegisterWindowClass()
            {
                WNDCLASS wc = { 0 };
                wc.style = GetClassStyle();
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hIcon = NULL;
                wc.lpfnWndProc = CWindowWnd::__WndProc;

            __WndProc是CWindowWnd的一個靜態成員,這個函數值得看一下:

            LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
            {
                CWindowWnd* pThis = NULL;
                if( uMsg == WM_NCCREATE ) {
                    LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
                    pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
                    pThis->m_hWnd = hWnd;
                    ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
                } 
                else {
                    pThis = reinterpret_cast<CWindowWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
                    if( uMsg == WM_NCDESTROY && pThis != NULL ) {
                        LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
                        ::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);
                        if( pThis->m_bSubclassed ) pThis->Unsubclass();
                        pThis->m_hWnd = NULL;
                        pThis->OnFinalMessage(hWnd);
                        return lRes;
                    }
                }
                if( pThis != NULL ) {
                    return pThis->HandleMessage(uMsg, wParam, lParam);
                } 
                else {
                    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
                }
            }
            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

            針對WM_NCCREATE這個消息有一個管用技巧,先復習下這個消息:

            The WM_NCCREATE message is sent prior to the WM_CREATE message when a window is first created.

            我的理解中,這個消息應該是窗口收到的第一個消息。

            還有WM_NCDESTROY這個特殊的消息。

            當然了,還有這個牛逼的戲法:

            ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));

            總的來說一句話,兩個消息NC create destroy對應的應該有連個函數,但是原本的OnNcCreate響應隱藏在了__WndProc中,還有一個函數OnFinalMessage。this指針藏在SetWindowLongPtr(hWnd, GWLP_USERDATA,,,

            好了底層需要注意的就只有這兩個函數,其他的消息都應該是拋給子類去處理了。

            既然是玩directUi,就重點關注一下WM_NCPAINT消息,也一個也很重要的消息WM_NCHITTEST。

            不知道為什么這里用的都是NC系列消息。

            NC應該是理解成none client,初步觀察Duilib的size拖拉支持是使用NCHITTEST+SIZE消息來實現的。

            看NCPAINT消息體里邊沒有任何代碼這很詭異,所以還是看看完整的消息響應函數,是不是漏掉了什么:

                LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
                {
                    LRESULT lRes = 0;
                    BOOL bHandled = TRUE;
                    switch( uMsg ) {
                    case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
                    case WM_CLOSE:         lRes = OnClose(uMsg, wParam, lParam, bHandled); break;
                    case WM_DESTROY:       lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break;
                    case WM_NCACTIVATE:    lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
                    case WM_NCCALCSIZE:    lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
                    case WM_NCPAINT:       lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;
                    case WM_NCHITTEST:     lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
                    case WM_SIZE:          lRes = OnSize(uMsg, wParam, lParam, bHandled); break;
                    case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break;
                    case WM_SYSCOMMAND:    lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break;
                    default:
                        bHandled = FALSE;
                    }
                    if( bHandled ) return lRes;
                    if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;
                    return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
                }
            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

            乍看之下這里的消息處理至少分為三層,CWindowWnd派生類本身沒有處理的消息將會被送到m_pm中去處理,如果m_pm.MessageHandler返回false消息最后還是CWindowWnd處理。

            bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
            {
            //#ifdef _DEBUG
            //    switch( uMsg ) {
            //    case WM_NCPAINT:
            //    case WM_NCHITTEST:
            //    case WM_SETCURSOR:
            //       break;
            //    default:
            //       DUITRACE(_T("MSG: %-20s (%08ld)"), DUITRACEMSG(uMsg), ::GetTickCount());
            //    }
            //#endif
                // Not ready yet?
                if( m_hWndPaint == NULL ) return false;
                
                TNotifyUI* pMsg = NULL;
                while( pMsg = static_cast<TNotifyUI*>(m_aAsyncNotify.GetAt(0)) ) {
                    m_aAsyncNotify.Remove(0);
                    if( pMsg->pSender != NULL ) {
                        if( pMsg->pSender->OnNotify ) pMsg->pSender->OnNotify(pMsg);
                    }
                    for( int j = 0; j < m_aNotifiers.GetSize(); j++ ) {
                        static_cast<INotifyUI*>(m_aNotifiers[j])->Notify(*pMsg);
                    }
                    delete pMsg;
                }
                
                // Cycle through listeners
                for( int i = 0; i < m_aMessageFilters.GetSize(); i++ ) 
                {
                    bool bHandled = false;
                    LRESULT lResult = static_cast<IMessageFilterUI*>(m_aMessageFilters[i])->MessageHandler(uMsg, wParam, lParam, bHandled);
                    if( bHandled ) {
                        lRes = lResult;
                        return true;
                    }
                }
                // Custom handling of events
                switch( uMsg ) {
                case WM_APP + 1:
                    {
                        for( int i = 0; i < m_aDelayedCleanup.GetSize(); i++ ) 
                            delete static_cast<CControlUI*>(m_aDelayedCleanup[i]);
                        m_aDelayedCleanup.Empty();
                    }
                    break;
                case WM_CLOSE:
                    {
                        // Make sure all matching "closing" events are sent
                        TEventUI event = { 0 };
                        event.ptMouse = m_ptLastMousePos;
                        event.dwTimestamp = ::GetTickCount();
                        if( m_pEventHover != NULL ) {
                            event.Type = UIEVENT_MOUSELEAVE;
                            event.pSender = m_pEventHover;
                            m_pEventHover->Event(event);
                        }
                        if( m_pEventClick != NULL ) {
                            event.Type = UIEVENT_BUTTONUP;
                            event.pSender = m_pEventClick;
                            m_pEventClick->Event(event);
                        }
            
                        SetFocus(NULL);
            
                        // Hmmph, the usual Windows tricks to avoid
                        // focus loss...
                        HWND hwndParent = GetWindowOwner(m_hWndPaint);
                        if( hwndParent != NULL ) ::SetFocus(hwndParent);
                    }
                    break;
                case WM_ERASEBKGND:
                    {
                        // We'll do the painting here...
                        lRes = 1;
                    }
                    return true;
                case WM_PAINT:
                    {
                        // Should we paint?
                        RECT rcPaint = { 0 };
                        if( !::GetUpdateRect(m_hWndPaint, &rcPaint, FALSE) ) return true;
                        if( m_pRoot == NULL ) {
                            PAINTSTRUCT ps = { 0 };
                            ::BeginPaint(m_hWndPaint, &ps);
                            ::EndPaint(m_hWndPaint, &ps);
                            return true;
                        }            
                        // Do we need to resize anything?
                        // This is the time where we layout the controls on the form.
                        // We delay this even from the WM_SIZE messages since resizing can be
                        // a very expensize operation.
                        if( m_bUpdateNeeded ) {
                            m_bUpdateNeeded = false;
                            RECT rcClient = { 0 };
                            ::GetClientRect(m_hWndPaint, &rcClient);
                            if( !::IsRectEmpty(&rcClient) ) {
                                if( m_pRoot->IsUpdateNeeded() ) {
                                    m_pRoot->SetPos(rcClient);
                                    if( m_hDcOffscreen != NULL ) ::DeleteDC(m_hDcOffscreen);
                                    if( m_hDcBackground != NULL ) ::DeleteDC(m_hDcBackground);
                                    if( m_hbmpOffscreen != NULL ) ::DeleteObject(m_hbmpOffscreen);
                                    if( m_hbmpBackground != NULL ) ::DeleteObject(m_hbmpBackground);
                                    m_hDcOffscreen = NULL;
                                    m_hDcBackground = NULL;
                                    m_hbmpOffscreen = NULL;
                                    m_hbmpBackground = NULL;
                                }
                                else {
                                    CControlUI* pControl = NULL;
                                    while( pControl = m_pRoot->FindControl(__FindControlFromUpdate, NULL, UIFIND_VISIBLE | UIFIND_ME_FIRST) ) {
                                        pControl->SetPos( pControl->GetPos() );
                                    }
                                }
                                // We'll want to notify the window when it is first initialized
                                // with the correct layout. The window form would take the time
                                // to submit swipes/animations.
                                if( m_bFirstLayout ) {
                                    m_bFirstLayout = false;
                                    SendNotify(m_pRoot, DUI_MSGTYPE_WINDOWINIT,  0, 0, false);
                                }
                            }
                        }
                        // Set focus to first control?
                        if( m_bFocusNeeded ) {
                            SetNextTabControl();
                        }
                        //
                        // Render screen
                        //
                        // Prepare offscreen bitmap?
                        if( m_bOffscreenPaint && m_hbmpOffscreen == NULL )
                        {
                            RECT rcClient = { 0 };
                            ::GetClientRect(m_hWndPaint, &rcClient);
                            m_hDcOffscreen = ::CreateCompatibleDC(m_hDcPaint);
                            m_hbmpOffscreen = ::CreateCompatibleBitmap(m_hDcPaint, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); 
                            ASSERT(m_hDcOffscreen);
                            ASSERT(m_hbmpOffscreen);
                        }
                        // Begin Windows paint
                        PAINTSTRUCT ps = { 0 };
                        ::BeginPaint(m_hWndPaint, &ps);
                        if( m_bOffscreenPaint )
                        {
                            HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(m_hDcOffscreen, m_hbmpOffscreen);
                            int iSaveDC = ::SaveDC(m_hDcOffscreen);
                            if( m_bAlphaBackground ) {
                                if( m_hbmpBackground == NULL ) {
                                    RECT rcClient = { 0 };
                                    ::GetClientRect(m_hWndPaint, &rcClient);
                                    m_hDcBackground = ::CreateCompatibleDC(m_hDcPaint);;
                                    m_hbmpBackground = ::CreateCompatibleBitmap(m_hDcPaint, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); 
                                    ASSERT(m_hDcBackground);
                                    ASSERT(m_hbmpBackground);
                                    ::SelectObject(m_hDcBackground, m_hbmpBackground);
                                    ::BitBlt(m_hDcBackground, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left,
                                        ps.rcPaint.bottom - ps.rcPaint.top, ps.hdc, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
                                }
                                else
                                    ::SelectObject(m_hDcBackground, m_hbmpBackground);
                                ::BitBlt(m_hDcOffscreen, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left,
                                    ps.rcPaint.bottom - ps.rcPaint.top, m_hDcBackground, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
                            }
                            m_pRoot->DoPaint(m_hDcOffscreen, ps.rcPaint);
                            for( int i = 0; i < m_aPostPaintControls.GetSize(); i++ ) {
                                CControlUI* pPostPaintControl = static_cast<CControlUI*>(m_aPostPaintControls[i]);
                                pPostPaintControl->DoPostPaint(m_hDcOffscreen, ps.rcPaint);
                            }
                            ::RestoreDC(m_hDcOffscreen, iSaveDC);
                            ::BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left,
                                ps.rcPaint.bottom - ps.rcPaint.top, m_hDcOffscreen, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
                            ::SelectObject(m_hDcOffscreen, hOldBitmap);
            
                            if( m_bShowUpdateRect ) {
                                HPEN hOldPen = (HPEN)::SelectObject(ps.hdc, m_hUpdateRectPen);
                                ::SelectObject(ps.hdc, ::GetStockObject(HOLLOW_BRUSH));
                                ::Rectangle(ps.hdc, rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom);
                                ::SelectObject(ps.hdc, hOldPen);
                            }
                        }
                        else
                        {
                            // A standard paint job
                            int iSaveDC = ::SaveDC(ps.hdc);
                            m_pRoot->DoPaint(ps.hdc, ps.rcPaint);
                            ::RestoreDC(ps.hdc, iSaveDC);
                        }
                        // All Done!
                        ::EndPaint(m_hWndPaint, &ps);
                    }
                    // If any of the painting requested a resize again, we'll need
                    // to invalidate the entire window once more.
                    if( m_bUpdateNeeded ) {
                        ::InvalidateRect(m_hWndPaint, NULL, FALSE);
                    }
                    return true;
                case WM_PRINTCLIENT:
                    {
                        RECT rcClient;
                        ::GetClientRect(m_hWndPaint, &rcClient);
                        HDC hDC = (HDC) wParam;
                        int save = ::SaveDC(hDC);
                        m_pRoot->DoPaint(hDC, rcClient);
                        // Check for traversing children. The crux is that WM_PRINT will assume
                        // that the DC is positioned at frame coordinates and will paint the child
                        // control at the wrong position. We'll simulate the entire thing instead.
                        if( (lParam & PRF_CHILDREN) != 0 ) {
                            HWND hWndChild = ::GetWindow(m_hWndPaint, GW_CHILD);
                            while( hWndChild != NULL ) {
                                RECT rcPos = { 0 };
                                ::GetWindowRect(hWndChild, &rcPos);
                                ::MapWindowPoints(HWND_DESKTOP, m_hWndPaint, reinterpret_cast<LPPOINT>(&rcPos), 2);
                                ::SetWindowOrgEx(hDC, -rcPos.left, -rcPos.top, NULL);
                                // NOTE: We use WM_PRINT here rather than the expected WM_PRINTCLIENT
                                //       since the latter will not print the nonclient correctly for
                                //       EDIT controls.
                                ::SendMessage(hWndChild, WM_PRINT, wParam, lParam | PRF_NONCLIENT);
                                hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT);
                            }
                        }
                        ::RestoreDC(hDC, save);
                    }
                    break;
                case WM_GETMINMAXINFO:
                    {
                        LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
                        if( m_szMinWindow.cx > 0 ) lpMMI->ptMinTrackSize.x = m_szMinWindow.cx;
                        if( m_szMinWindow.cy > 0 ) lpMMI->ptMinTrackSize.y = m_szMinWindow.cy;
                        if( m_szMaxWindow.cx > 0 ) lpMMI->ptMaxTrackSize.x = m_szMaxWindow.cx;
                        if( m_szMaxWindow.cy > 0 ) lpMMI->ptMaxTrackSize.y = m_szMaxWindow.cy;
                    }
                    break;
                case WM_SIZE:
                    {
                        if( m_pFocus != NULL ) {
                            TEventUI event = { 0 };
                            event.Type = UIEVENT_WINDOWSIZE;
                            event.pSender = m_pFocus;
                            event.dwTimestamp = ::GetTickCount();
                            m_pFocus->Event(event);
                        }
                        if( m_pRoot != NULL ) m_pRoot->NeedUpdate();
                    }
                    return true;
                case WM_TIMER:
                    {
                        for( int i = 0; i < m_aTimers.GetSize(); i++ ) {
                            const TIMERINFO* pTimer = static_cast<TIMERINFO*>(m_aTimers[i]);
                            if( pTimer->hWnd == m_hWndPaint && pTimer->uWinTimer == LOWORD(wParam) && pTimer->bKilled == false) {
                                TEventUI event = { 0 };
                                event.Type = UIEVENT_TIMER;
                                event.pSender = pTimer->pSender;
                                event.wParam = pTimer->nLocalID;
                                event.dwTimestamp = ::GetTickCount();
                                pTimer->pSender->Event(event);
                                break;
                            }
                        }
                    }
                    break;
                case WM_MOUSEHOVER:
                    {
                        m_bMouseTracking = false;
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        CControlUI* pHover = FindControl(pt);
                        if( pHover == NULL ) break;
                        // Generate mouse hover event
                        if( m_pEventHover != NULL ) {
                            TEventUI event = { 0 };
                            event.ptMouse = pt;
                            event.Type = UIEVENT_MOUSEHOVER;
                            event.pSender = m_pEventHover;
                            event.dwTimestamp = ::GetTickCount();
                            m_pEventHover->Event(event);
                        }
                        // Create tooltip information
                        CDuiString sToolTip = pHover->GetToolTip();
                        if( sToolTip.IsEmpty() ) return true;
                        ::ZeroMemory(&m_ToolTip, sizeof(TOOLINFO));
                        m_ToolTip.cbSize = sizeof(TOOLINFO);
                        m_ToolTip.uFlags = TTF_IDISHWND;
                        m_ToolTip.hwnd = m_hWndPaint;
                        m_ToolTip.uId = (UINT_PTR) m_hWndPaint;
                        m_ToolTip.hinst = m_hInstance;
                        m_ToolTip.lpszText = const_cast<LPTSTR>( (LPCTSTR) sToolTip );
                        m_ToolTip.rect = pHover->GetPos();
                        if( m_hwndTooltip == NULL ) {
                            m_hwndTooltip = ::CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_hWndPaint, NULL, m_hInstance, NULL);
                            ::SendMessage(m_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM) &m_ToolTip);
                        }
                        ::SendMessage(m_hwndTooltip, TTM_SETTOOLINFO, 0, (LPARAM) &m_ToolTip);
                        ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &m_ToolTip);
                    }
                    return true;
                case WM_MOUSELEAVE:
                    {
                        if( m_hwndTooltip != NULL ) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip);
                        if( m_bMouseTracking ) ::SendMessage(m_hWndPaint, WM_MOUSEMOVE, 0, (LPARAM) -1);
                        m_bMouseTracking = false;
                    }
                    break;
                case WM_MOUSEMOVE:
                    {
                        // Start tracking this entire window again...
                        if( !m_bMouseTracking ) {
                            TRACKMOUSEEVENT tme = { 0 };
                            tme.cbSize = sizeof(TRACKMOUSEEVENT);
                            tme.dwFlags = TME_HOVER | TME_LEAVE;
                            tme.hwndTrack = m_hWndPaint;
                            tme.dwHoverTime = m_hwndTooltip == NULL ? 400UL : (DWORD) ::SendMessage(m_hwndTooltip, TTM_GETDELAYTIME, TTDT_INITIAL, 0L);
                            _TrackMouseEvent(&tme);
                            m_bMouseTracking = true;
                        }
                        // Generate the appropriate mouse messages
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        m_ptLastMousePos = pt;
                        CControlUI* pNewHover = FindControl(pt);
                        if( pNewHover != NULL && pNewHover->GetManager() != this ) break;
                        TEventUI event = { 0 };
                        event.ptMouse = pt;
                        event.dwTimestamp = ::GetTickCount();
                        if( pNewHover != m_pEventHover && m_pEventHover != NULL ) {
                            event.Type = UIEVENT_MOUSELEAVE;
                            event.pSender = m_pEventHover;
                            m_pEventHover->Event(event);
                            m_pEventHover = NULL;
                            if( m_hwndTooltip != NULL ) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip);
                        }
                        if( pNewHover != m_pEventHover && pNewHover != NULL ) {
                            event.Type = UIEVENT_MOUSEENTER;
                            event.pSender = pNewHover;
                            pNewHover->Event(event);
                            m_pEventHover = pNewHover;
                        }
                        if( m_pEventClick != NULL ) {
                            event.Type = UIEVENT_MOUSEMOVE;
                            event.pSender = m_pEventClick;
                            m_pEventClick->Event(event);
                        }
                        else if( pNewHover != NULL ) {
                            event.Type = UIEVENT_MOUSEMOVE;
                            event.pSender = pNewHover;
                            pNewHover->Event(event);
                        }
                    }
                    break;
                case WM_LBUTTONDOWN:
                    {
                        // We alway set focus back to our app (this helps
                        // when Win32 child windows are placed on the dialog
                        // and we need to remove them on focus change).
                        ::SetFocus(m_hWndPaint);
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        m_ptLastMousePos = pt;
                        CControlUI* pControl = FindControl(pt);
                        if( pControl == NULL ) break;
                        if( pControl->GetManager() != this ) break;
                        m_pEventClick = pControl;
                        pControl->SetFocus();
                        SetCapture();
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_BUTTONDOWN;
                        event.pSender = pControl;
                        event.wParam = wParam;
                        event.lParam = lParam;
                        event.ptMouse = pt;
                        event.wKeyState = (WORD)wParam;
                        event.dwTimestamp = ::GetTickCount();
                        pControl->Event(event);
                    }
                    break;
                case WM_LBUTTONDBLCLK:
                    {
                        ::SetFocus(m_hWndPaint);
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        m_ptLastMousePos = pt;
                        CControlUI* pControl = FindControl(pt);
                        if( pControl == NULL ) break;
                        if( pControl->GetManager() != this ) break;
                        SetCapture();
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_DBLCLICK;
                        event.pSender = pControl;
                        event.ptMouse = pt;
                        event.wKeyState = (WORD)wParam;
                        event.dwTimestamp = ::GetTickCount();
                        pControl->Event(event);
                        m_pEventClick = pControl;
                    }
                    break;
                case WM_LBUTTONUP:
                    {
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        m_ptLastMousePos = pt;
                        if( m_pEventClick == NULL ) break;
                        ReleaseCapture();
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_BUTTONUP;
                        event.pSender = m_pEventClick;
                        event.wParam = wParam;
                        event.lParam = lParam;
                        event.ptMouse = pt;
                        event.wKeyState = (WORD)wParam;
                        event.dwTimestamp = ::GetTickCount();
                        m_pEventClick->Event(event);
                        m_pEventClick = NULL;
                    }
                    break;
                case WM_RBUTTONDOWN:
                    {
                        ::SetFocus(m_hWndPaint);
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        m_ptLastMousePos = pt;
                        CControlUI* pControl = FindControl(pt);
                        if( pControl == NULL ) break;
                        if( pControl->GetManager() != this ) break;
                        pControl->SetFocus();
                        SetCapture();
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_RBUTTONDOWN;
                        event.pSender = pControl;
                        event.wParam = wParam;
                        event.lParam = lParam;
                        event.ptMouse = pt;
                        event.wKeyState = (WORD)wParam;
                        event.dwTimestamp = ::GetTickCount();
                        pControl->Event(event);
                        m_pEventClick = pControl;
                    }
                    break;
                case WM_CONTEXTMENU:
                    {
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        ::ScreenToClient(m_hWndPaint, &pt);
                        m_ptLastMousePos = pt;
                        if( m_pEventClick == NULL ) break;
                        ReleaseCapture();
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_CONTEXTMENU;
                        event.pSender = m_pEventClick;
                        event.ptMouse = pt;
                        event.wKeyState = (WORD)wParam;
                        event.lParam = (LPARAM)m_pEventClick;
                        event.dwTimestamp = ::GetTickCount();
                        m_pEventClick->Event(event);
                        m_pEventClick = NULL;
                    }
                    break;
                case WM_MOUSEWHEEL:
                    {
                        POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
                        ::ScreenToClient(m_hWndPaint, &pt);
                        m_ptLastMousePos = pt;
                        CControlUI* pControl = FindControl(pt);
                        if( pControl == NULL ) break;
                        if( pControl->GetManager() != this ) break;
                        int zDelta = (int) (short) HIWORD(wParam);
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_SCROLLWHEEL;
                        event.pSender = pControl;
                        event.wParam = MAKELPARAM(zDelta < 0 ? SB_LINEDOWN : SB_LINEUP, 0);
                        event.lParam = lParam;
                        event.wKeyState = MapKeyState();
                        event.dwTimestamp = ::GetTickCount();
                        pControl->Event(event);
            
                        // Let's make sure that the scroll item below the cursor is the same as before...
                        ::SendMessage(m_hWndPaint, WM_MOUSEMOVE, 0, (LPARAM) MAKELPARAM(m_ptLastMousePos.x, m_ptLastMousePos.y));
                    }
                    break;
                case WM_CHAR:
                    {
                        if( m_pFocus == NULL ) break;
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_CHAR;
                        event.chKey = (TCHAR)wParam;
                        event.ptMouse = m_ptLastMousePos;
                        event.wKeyState = MapKeyState();
                        event.dwTimestamp = ::GetTickCount();
                        m_pFocus->Event(event);
                    }
                    break;
                case WM_KEYDOWN:
                    {
                        if( m_pFocus == NULL ) break;
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_KEYDOWN;
                        event.chKey = (TCHAR)wParam;
                        event.ptMouse = m_ptLastMousePos;
                        event.wKeyState = MapKeyState();
                        event.dwTimestamp = ::GetTickCount();
                        m_pFocus->Event(event);
                        m_pEventKey = m_pFocus;
                    }
                    break;
                case WM_KEYUP:
                    {
                        if( m_pEventKey == NULL ) break;
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_KEYUP;
                        event.chKey = (TCHAR)wParam;
                        event.ptMouse = m_ptLastMousePos;
                        event.wKeyState = MapKeyState();
                        event.dwTimestamp = ::GetTickCount();
                        m_pEventKey->Event(event);
                        m_pEventKey = NULL;
                    }
                    break;
                case WM_SETCURSOR:
                    {
                        if( LOWORD(lParam) != HTCLIENT ) break;
                        if( m_bMouseCapture ) return true;
            
                        POINT pt = { 0 };
                        ::GetCursorPos(&pt);
                        ::ScreenToClient(m_hWndPaint, &pt);
                        CControlUI* pControl = FindControl(pt);
                        if( pControl == NULL ) break;
                        if( (pControl->GetControlFlags() & UIFLAG_SETCURSOR) == 0 ) break;
                        TEventUI event = { 0 };
                        event.Type = UIEVENT_SETCURSOR;
                        event.wParam = wParam;
                        event.lParam = lParam;
                        event.ptMouse = pt;
                        event.wKeyState = MapKeyState();
                        event.dwTimestamp = ::GetTickCount();
                        pControl->Event(event);
                    }
                    return true;
                case WM_NOTIFY:
                    {
                        LPNMHDR lpNMHDR = (LPNMHDR) lParam;
                        if( lpNMHDR != NULL ) lRes = ::SendMessage(lpNMHDR->hwndFrom, OCM__BASE + uMsg, wParam, lParam);
                        return true;
                    }
                    break;
                case WM_COMMAND:
                    {
                        if( lParam == 0 ) break;
                        HWND hWndChild = (HWND) lParam;
                        lRes = ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
                        return true;
                    }
                    break;
                case WM_CTLCOLOREDIT:
                case WM_CTLCOLORSTATIC:
                    {
                        // Refer To: http://msdn.microsoft.com/en-us/library/bb761691(v=vs.85).aspx
                        // Read-only or disabled edit controls do not send the WM_CTLCOLOREDIT message; instead, they send the WM_CTLCOLORSTATIC message.
                        if( lParam == 0 ) break;
                        HWND hWndChild = (HWND) lParam;
                        lRes = ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
                        return true;
                    }
                    break;
                default:
                    break;
                }
            
                pMsg = NULL;
                while( pMsg = static_cast<TNotifyUI*>(m_aAsyncNotify.GetAt(0)) ) {
                    m_aAsyncNotify.Remove(0);
                    if( pMsg->pSender != NULL ) {
                        if( pMsg->pSender->OnNotify ) pMsg->pSender->OnNotify(pMsg);
                    }
                    for( int j = 0; j < m_aNotifiers.GetSize(); j++ ) {
                        static_cast<INotifyUI*>(m_aNotifiers[j])->Notify(*pMsg);
                    }
                    delete pMsg;
                }
            
                return false;
            }
            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

            我去這里代碼有點多,先簡單捋一下,首先處理了如下消息:

            WM_CTLCOLOREDIT:
            WM_CTLCOLORSTATIC
            WM_COMMAND:
            WM_NOTIFY:
            WM_SETCURSOR:
            WM_KEYUP
            WM_KEYDOWN
            WM_CHAR
            WM_MOUSEWHEEL
            WM_CONTEXTMENU
            WM_RBUTTONDOWN
            WM_LBUTTONUP
            WM_LBUTTONDBLCLK
            WM_LBUTTONDOWN
            WM_MOUSEMOVE
            WM_MOUSELEAVE
            WM_MOUSEHOVER
            WM_TIMER
            WM_SIZE
            WM_GETMINMAXINFO
            WM_PRINTCLIENT
            WM_PAINT
            WM_ERASEBKGND
            WM_CLOSE
            WM_APP

            除了這些消息還有一個特別的東西需要留意:

            m_aAsyncNotify以后再分析

             

             

            .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

            posted @ 2013-03-07 21:39 Enic 閱讀(2223) | 評論 (0)編輯 收藏

            質量最大vczh粉(402740419) 10:13:17

            nobody(1575393351)  10:10:09
            無鎖隊列,怎么可能

            質量最大vczh粉(402740419) 10:13:23

            用link做,輕輕松松

            nobody(1575393351) 10:13:40

            多個線程同時從隊列里面取,怎么可能不加鎖。。

            uczh.0xDEADBEEF(365128087) 10:13:44

            他已經發請求了

            vczh四號粉絲(342775210) 10:13:51

            可以不加鎖

            質量最大vczh粉(402740419) 10:13:51

            用link做,真心不用加鎖

            vczh四號粉絲(342775210) 10:13:55

            不過必須用cas

            質量最大vczh粉(402740419) 10:14:03

            CAS是啥

            vczh四號粉絲(342775210) 10:14:06

            否則做不了多線程的并發

            nobody(1575393351) 10:14:13

            link是什么東西

            質量最大vczh粉(402740419) 10:30:26

            陳梓瀚<vczh@163.com>  10:27:16
            用interlocked compare exchange
            當tail == null就換一個new link進去
            這樣偏麻煩

            vczh四號粉絲(342775210) 10:30:28

            會把問題復雜化

            質量最大vczh粉(402740419) 10:30:29

            有簡單的辦法

            uczh.0xDEADBEEF(365128087) 10:30:30

            但性能很好的

            質量最大vczh粉(402740419) 10:30:43

            類似ngxqueue的辦法,保證鏈表里始終有一個結點

            質量最大vczh粉(402740419) 10:30:49

            這樣可以避免很多麻煩

            uczh.0xDEADBEEF(365128087) 10:31:03

            質量最大vczh粉(402740419) 10:31:07

            只有構造和析構的時候 多線程訪問會出問題,但這時候一般又不會多線程訪問

            vczh.Iskandar<vczh@163.com> 10:31:17

            就算如此你也要對tail->next == null的時候做判斷嘛

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:31:22

            質量最大vczh粉(402740419)  10:31:07
            只有構造和析構的時候 多線程訪問會出問題,但這時候一般又不會多線程訪問
            不要做任何假設

            vczh.Iskandar<vczh@163.com> 10:31:26

            這樣才能避免兩個線程同時push

            質量最大vczh粉(402740419) 10:31:48

            VCZH.粉絲數組[0](85126585)  10:31:22
            質量最大vczh粉(402740419)  10:31:07
            只有構造和析構的時候 多線程訪問會出問題,但這時候一般又不會多線程訪問
            不要做任何假設
            不是假設,構造還沒完成的時候就把對象傳給多個線程從設計上來說就是有毛病的

            質量最大vczh粉(402740419) 10:31:59

            析構也類似

            質量最大vczh粉(402740419) 10:32:14

            性質上和你在別的線程進行了野指針操作沒有區別

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:32:21

            ooseven(147340642) 10:32:31

            這樣設計的話,對象的生命周期很難控制

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:32:58

            reference counting嘛

            質量最大vczh粉(402740419) 10:33:00

            肯定是構造完了,才丟給shared_ptr或者別的什么東西,然后才會多線程考慮持有這個對象

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:33:02

            現在流行

            vczh.Iskandar<vczh@163.com> 10:33:08

            析構的時候

            vczh.Iskandar<vczh@163.com> 10:33:13

            肯定是所有shared_ptr都完蛋了

            vczh.Iskandar<vczh@163.com> 10:33:17

            所以這個時候也不會有人訪問了

            質量最大vczh粉(402740419) 10:33:36

            陳梓瀚<vczh@163.com>  10:31:17
            就算如此你也要對tail->next == null的時候做判斷嘛
            嗯嗯,compareandswap就是這里啊

            vczh四號粉絲(342775210) 10:34:23

            不僅僅是null的判斷吧

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:34:33

            循環隊列里邊

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:34:44

            tail->next == head

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:34:50

            貌似這樣的

            質量最大vczh粉(402740419) 10:34:56

            循環隊列?

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:35:04

            ring

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:35:06

            buffer

            質量最大vczh粉(402740419) 10:35:15

            ringbuffer是另一個概念= =

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:35:24

            囧,我錯了

            質量最大vczh粉(402740419) 10:35:41

            剛才那個是最簡單的,每個節點只能存一個pointer或者其它相同大小的東西

            vczh四號粉絲(342775210) 10:35:43

            http://blog.hesey.net/2011/09/resolve-aba-by-atomicstampedreference.html

            質量最大vczh粉(402740419) 10:37:16

            = = 堆棧這么做是找死啊

            質量最大vczh粉(402740419) 10:37:19

            就是算法有問題

            vczh.Iskandar<vczh@163.com> 10:37:50

            我覺得這個例子有問題

            vczh.Iskandar<vczh@163.com> 10:37:55

            你每一次push新數據進去的時候

            vczh四號粉絲(342775210) 10:37:57

            你的系統先把10Wtps過了,再說并發

            vczh.Iskandar<vczh@163.com> 10:38:04

            都不能重用節點

            vczh.Iskandar<vczh@163.com> 10:38:06

            都必須new一個新的

            質量最大vczh粉(402740419) 10:38:45

            vczh四號粉絲(342775210)  10:37:57
            你的系統先把10Wtps過了,再說并發
            噗,我的服務端是單進程多線程模型

            質量最大vczh粉(402740419) 10:38:53

            客戶端才在搞多線程

            質量最大vczh粉(402740419) 10:39:04

            說錯了

            質量最大vczh粉(402740419) 10:39:08

            服務端是單線程多金正

            質量最大vczh粉(402740419) 10:41:02

            我的引擎里當初做一個類似tbb那種task式的并行框架(或者類似boost.asio)

            質量最大vczh粉(402740419) 10:41:20

            因為趕著出工,直接拿一個lockfree的list就上了

            小老鼠(273245994) 10:41:25

            沈陽發生爆炸了

            質量最大vczh粉(402740419) 10:41:38

            結果性能還可以

            vczh.Iskandar<vczh@163.com> 10:41:43

            什么爆炸

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:42:35

            因為趕著出工,直接拿一個lockfree的list就上了
            自己寫的?

            質量最大vczh粉(402740419) 10:42:51

            很久很久很久以前寫的

            質量最大vczh粉(402740419) 10:43:05

            然后寫這個的時候不知道mem barrier

            質量最大vczh粉(402740419) 10:43:11

            加到引擎里的時候 加了下barrier

            小老鼠(273245994) 10:43:21

            9時,太原街地下通道

            質量最大vczh粉(402740419) 10:43:34

            當時還問了這兩位將近一天……

            小老鼠(273245994) 10:43:46

            附近1公里都有震感

            小老鼠(273245994) 10:43:57

            你說這次會不會還是死35人.

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:44:27

            牛逼

            裝配腦袋(2380479792) 10:44:37

            兩·會就不讓他們好好開

             

            小老鼠(273245994) 10:43:57

            你說這次會不會還是死35人.

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:44:27

            牛逼

            裝配腦袋(2380479792) 10:44:37

            兩·會就不讓他們好好開

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:44:40

            我遇到這個第一想法是開源的弄一個來

            御虛舟北(314969051) 10:44:41

            又黑人

            質量最大vczh粉(402740419) 10:45:32

            VCZH.粉絲數組[0](85126585)  10:44:40
            我遇到這個第一想法是開源的弄一個來
            假設需要一套整塊功能,肯定用開源的

            質量最大vczh粉(402740419) 10:45:46

            如果只需求一個點…… 對我們搞移動的來說,port成本太高了……

            質量最大vczh粉(402740419) 10:46:00

            不過本質上來說這個還是幾乎算是用開源的

            質量最大vczh粉(402740419) 10:46:03

            只是我人肉翻譯了下而已

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:46:35

            所以昨天被問到這個問題,我很反感那個家伙,,,

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:46:44

            尼瑪問這就是問我看過類似的帖子沒,,,

            質量最大vczh粉(402740419) 10:47:16

            帖子?

            vczh一千號粉絲(327385942) 10:47:29

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:47:41

            就是說我看過討論類似的論文沒有

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:47:47

            看過就能說兩句

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:47:58

            沒看過,面試那一點時間能想出來

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:48:01

            還見鬼了

            質量最大vczh粉(402740419) 10:48:17

            ??

            質量最大vczh粉(402740419) 10:48:24

            我曾經面試一個 剛畢業的小伙子,也談不上多優秀

            質量最大vczh粉(402740419) 10:48:32

            我面試就問的lock-free的隊列

            御虛舟北(314969051) 10:48:33

            剛畢業的小伙子

            質量最大vczh粉(402740419) 10:48:38

            還不是linked-list

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:48:44

            自己想出來了?

            質量最大vczh粉(402740419) 10:48:44

            是deque的

            質量最大vczh粉(402740419) 10:49:03

            自己肯定想不出來,但已經摸到邊了啊,我稍微誘導了一下

            質量最大vczh粉(402740419) 10:49:05

            就出來了

            vczh.Isotope(75497789) 10:49:27

            菊苣們,這里能問算法題不?

            質量最大vczh粉(402740419) 10:49:38

            知道基本概念了這就是很直觀的東西,需要上升到論文層面么……

            質量最大vczh粉(402740419) 10:49:45

            復雜一點的數據結構可能需要

            質量最大vczh粉(402740419) 10:49:48

            至少隊列不需要啊= =

            質量最大vczh粉(402740419) 10:50:18

            啥算法題?工作需要還是自己瞎折騰

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:50:25

            你考慮這些和我的方式不太一樣,我覺得這個東西了解就行了,自己做是下下策
            我是不是得改改了?

            vczh.Isotope(75497789) 10:50:44

            用1*2的矩形去覆蓋m*n的矩形(m*n是偶數),問一共有多少種方法

            質量最大vczh粉(402740419) 10:50:52

            VCZH.粉絲數組[0](85126585)  10:50:26
            你考慮這些和我的方式不太一樣,我覺得這個東西了解就行了,自己做是下下策
            做事的方式 和考察、自我考察的方式是兩碼事

            質量最大vczh粉(402740419) 10:51:31

            不然vczh大牛也不會做編譯器和GUI了,反正也沒人用

            vczh.Iskandar<vczh@163.com> 10:51:51

            小老鼠(273245994) 10:52:15

            內傷了

            質量最大vczh粉(402740419) 10:52:38

            vczh.Isotope(75497789)  10:50:44
            用1*2的矩形去覆蓋m*n的矩形(m*n是偶數),問一共有多少種方法
            ACM題?滾邊去。我會,就是不告訴你

            質量最大vczh粉(402740419) 10:52:40

            ACM毒害人

            vczh.Iskandar<vczh@163.com> 10:52:54

            做ACM踢掉(逃

            質量最大vczh粉(402740419) 10:53:02

            vczh.Isotope(75497789) 10:53:05

            不是ACM題

            vczh的腦殘粉(195719555) 10:53:08

            vczh.Ismeow(65200296) 10:53:10

            為什么踢掉……

            vczh.Iskandar<vczh@163.com> 10:53:14

            這些就是

            vczh.Isotope(75497789) 10:53:17

            好像是MS面試題

            vczh.Iskandar<vczh@163.com> 10:53:21

            這個群使用來討論奇技淫巧的

            vczh.Iskandar<vczh@163.com> 10:53:27

            這是google的面試題,M$才不面這個

            vczh.Konobuta(450635425) 10:53:48

            看了下 

            vczh.Konobuta(450635425) 10:54:05

            用了原子指令 

            質量最大vczh粉(402740419) 10:54:07

            這是百度的面試題,google才不面這個

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:54:08

            質量最大vczh粉(402740419)  10:50:52
            VCZH.粉絲數組[0](85126585)  10:50:26
            你考慮這些和我的方式不太一樣,我覺得這個東西了解就行了,自己做是下下策
            做事的方式 和考察、自我考察的方式是兩碼事
            不然vczh大牛也不會做編譯器和GUI了,反正也沒人用
            受教了,擠時間還是多把這些東西實現一下

            vczh一千號粉絲(327385942) 10:54:50

            vczh一千號粉絲(327385942) 10:55:12

            做acm題還是不錯的

            Sean(123983971) 10:55:15

            小矩形可以重疊嗎?

            vczh.Konobuta(450635425) 10:55:16

            實際上還是相當于加鎖,只是粒度更小 

            vczh.Konobuta(450635425) 10:55:32

            就怕有的平臺不支持 

            vczh.Iskandar<vczh@163.com> 10:55:42

            不支持CAS的平臺

            vczh.Iskandar<vczh@163.com> 10:55:52

            等你學會編程之后

            vczh.Iskandar<vczh@163.com> 10:56:02

            早就消失了

            vczh.Konobuta(450635425) 10:54:05

            用了原子指令 

            質量最大vczh粉(402740419) 10:54:07

            這是百度的面試題,google才不面這個

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:54:08

            質量最大vczh粉(402740419)  10:50:52
            VCZH.粉絲數組[0](85126585)  10:50:26
            你考慮這些和我的方式不太一樣,我覺得這個東西了解就行了,自己做是下下策
            做事的方式 和考察、自我考察的方式是兩碼事
            不然vczh大牛也不會做編譯器和GUI了,反正也沒人用
            受教了,擠時間還是多把這些東西實現一下

            vczh一千號粉絲(327385942) 10:54:50

            vczh一千號粉絲(327385942) 10:55:12

            做acm題還是不錯的

            Sean(123983971) 10:55:15

            小矩形可以重疊嗎?

            vczh.Konobuta(450635425) 10:55:16

            實際上還是相當于加鎖,只是粒度更小 

            vczh.Konobuta(450635425) 10:55:32

            就怕有的平臺不支持 

            vczh.Iskandar<vczh@163.com> 10:55:42

            不支持CAS的平臺

            vczh.Iskandar<vczh@163.com> 10:55:52

            等你學會編程之后

            vczh.Iskandar<vczh@163.com> 10:56:02

            早就消失了

            vczh.Konobuta(450635425) 10:56:40

            萬一有呢? 

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:56:43

            vczh.Iskandar<vczh@163.com>  10:55:42
            不支持CAS的平臺
            等你學會編程之后
            早就消失了
            確實,我沒見過,除了學校C51單片機

            裝配腦袋(2380479792) 10:56:50

            連ARM都支持

            vczh.Iskandar<vczh@163.com> 10:56:50

            就是沒有

            裝配腦袋(2380479792) 10:57:02

            不支持沒法辦事

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:57:05

            如果有,那么肯定是中斷來做時分的

            vczh.Ismeow(65200296) 10:57:04

            51這種平臺你會做什么搶占式Multiprogramming么……

            裝配腦袋(2380479792) 10:57:07

            顯卡都支持。。

            vczh.Ismeow(65200296) 10:57:10

            我相信不會吧

            vczh.Konobuta(450635425) 10:57:24

            好吧 

            vczh.Konobuta(450635425) 10:57:39

            我也換成這個 

            vczh.Iskandar<vczh@163.com> 10:57:59

            再說了,如果不用CAS,你是沒有任何辦法的

            質量最大vczh粉(402740419) 10:58:25

            不支持CAS的設備一般就是單核設備了吧

            vczh.腦殘粉(50923132) 10:58:27

            沒有CAS,同步只能

            質量最大vczh粉(402740419) 10:58:42

            單核設備 還是能保證單條指令原子性的吧

            vczh.Ismeow(65200296) 10:58:52

            不支持CAS的設備一般是不支持多任務的設備……

            質量最大vczh粉(402740419) 10:59:03

            用中斷做分時任務是OK的

            vczh.Ismeow(65200296) 10:59:27

            問題是就那點可憐的資源……

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:59:51

            多核 多中斷

            VCZH.粉絲數組[0]<errorcpp@qq.com> 10:59:55

            就sb了

            vczh.Ismeow(65200296) 10:59:56

            你做個什么調度就爆了

            VCZH.粉絲數組[0]<errorcpp@qq.com> 11:00:17

            不過這樣SB的CPU估計沒人用

            從未來‏?過‪(815330718) 11:00:33

            沒有cas, 硬生生的 用不可屏蔽中斷+變量 造一個...

            vczh.Ismeow(65200296) 11:00:41

            從未來‏?過‪(815330718) 11:00:42

            (逃

            vczh.Ismeow(65200296) 11:00:54

            NMI弄一個,不過這么弄就要硬件支持吧

            vczh.Konobuta(450635425) 11:01:08

            uczh.0xDEADBEEF(365128087) 11:01:24

            vczh.Iskandar<vczh@163.com> 11:02:10

            連cas都沒有的硬件

            從未來‏?過‪(815330718) 11:02:16

            只會寫代碼,不如去種田
            http://www.oschina.net/news/38229/teach-kids-to-farm-not-code

            vczh.Iskandar<vczh@163.com> 11:02:18

            你想做多線程的事情

            小老鼠(273245994) 11:02:19

            http://slide.news.sina.com.cn/c/slide_1_2841_30492.html#p=1

            vczh.Iskandar<vczh@163.com> 11:02:21

            只能踩死

            質量最大vczh粉(402740419) 11:05:35

            vczh

            質量最大vczh粉(402740419) 11:05:43

            我今年6月份開始,要大規模做UI類的東西

            vczh.Iskandar<vczh@163.com> 11:05:53

            你不是早就做了嗎

            質量最大vczh粉(402740419) 11:06:11

            我什么時候大規模做過可商業化的UI…… 除了在百度

            vczh.Konobuta(450635425) 11:06:21

            vczh.Konobuta(450635425) 11:06:31

            教我 

            vczh.Iskandar<vczh@163.com> 11:06:41

            不是萌妹紙,滾!

            vczh.Konobuta(450635425) 11:06:47

            入群求節操(152606004) 11:06:50


            教我

            vczh.腦殘粉(50923132) 11:06:58

            vczh.Iskandar<vczh@163.com>  11:06:41
            不是萌妹紙,滾!

            御虛舟北(314969051) 11:07:00

            不是萌妹紙,滾!

            質量最大vczh粉(402740419) 11:07:08

            不是萌妹紙,滾!

            vczh.Konobuta(450635425) 11:07:11

            質量最大vczh粉(402740419) 11:07:12

            話說回來

            質量最大vczh粉(402740419) 11:07:22

            GacUI到那時候能完善到滿足我的需求么= =

            質量最大vczh粉(402740419) 11:07:30

            不然的話,我是用Qt呢還是Qt呢還是Qt呢?

             

             

             

            暫時的理解:

            隊列如果限定插入只從head,彈出只從tail,那么只要滿足head != tail就是,一讀取一寫就是安全的。


            posted @ 2013-03-04 11:14 Enic 閱讀(1502) | 評論 (0)編輯 收藏

            1.building vc solution under console
            "D:\Program Files\Microsoft Visual Studio 9.0
            \Common7\IDE\devenv" /build debug /out "aa.log" xxx.sln
            http://blog.csdn.net/sm_crystal/article/details/6993767

            2.emacs show line numbers
            M-x linum-mode (or global-linum-mode), and put (global-linum-mode t) in your ~/.emacs (or ~/.emacs.d/init.el) to enable it at startup.
            linum: separating line numbers from text
            find this pice of code in linum.el: (setq width (max with (length str)))
            change to (setq width (max width (+ (length str) 1)))
            conctol the line number format: (setq linum-format "%3d")
            set on for appointed mode:
            (setq linum-mode-inhibit-modes-list '(eshell-mode
                                                  shell-mode
                                                  erc-mode
                                                  jabber-roster-mode
                                                  jabber-chat-mode
                                                  gnus-group-mode
                                                  gnus-summary-mode
                                                  gnus-article-mode))

            (defadvice linum-on (around linum-on-inhibit-for-modes)
              "Stop the load of linum-mode for some major modes."
                (unless (member major-mode linum-mode-inhibit-modes-list)
                  ad-do-it))

            (ad-activate 'linum-on)
            compile .el to .elc: atl+x byte-compile-file
            http://www.emacswiki.org/emacs/LineNumbers

            3.using gzip - compress/uncompress file
            compress: gzip [file name]
            uncompress: gunzip [file name]
            keep the input file: gunzip [file.gz] -c >> [file]
            gunzip/gzip -c which simply writes the output stream to stdout
            compress all the files under a director: -r
            http://blog.csdn.net/yuyongpeng/article/details/1818717

            4.emacs do not auto save backup files
            (setq auto-save-default nil)

            5.emacs close file ctrl+x k

            posted @ 2013-03-04 09:10 Enic 閱讀(284) | 評論 (0)編輯 收藏

            3.1調試測試

            ×我們必須創建測試以重現問題

            ×我們必須多次運行測試以簡化問題

            ×我們必須重新運行測試以觀察運行過程

            ×我們必須重新運行測試以驗證修改是否成功

            ×每個版本發布之前,我們必須重新運行測試,以便發現將來不會再次出現,這種稱為回歸測試

            在調試過程中需要頻繁的進行自動測試,應此最好盡可能的采用自動化測試。通常通過使用自動化測試技術,可以更容易的進行全面測試,自動化測試的好處在于:

            ×可以重用已有測試

            ×可以進行一些困難的、無法手工執行的測試(如:大規模的隨機性測試)

            ×重復測試

            ×增強對軟件的信心

             

            3.2控制程序

                    通常,自動化測試必須模擬程序所處的環境---也就是說,測試必須提供程序的輸入,并且評估程序的輸出。但是模擬環境需要很多技巧,如果環境中包括和程序進行交互的用戶,自動測試就必須模擬真實的用戶(包括他們的所有能力)。

                    通過區分不同的接口,可以避開部分模擬難題,從而使得控制和評估都更易于自動化。下圖是典型的三層接口劃分:

            ×表現層處理和用戶(或者構建程序環境的任何事物)之間的交互

            ×功能層封裝程序的實際功能,功能獨立于表現層

            ×單元層把功能分解成多個單元,這些單元相互協作形成一個整體

            image

             

             

            3.3在表現層測試

            3.3.1低級交互

                    在最低級的抽象級別,用戶輸入被看做鼠標和鍵盤的事件流,這種事件流可以是被捕獲和重放,即用時間記錄器的時間流替代實際輸入設備的事件流。

            (PS:如果是在windows上測試需要UI交互的程序,貌似可以直接簡單的試用key_event mouse_event等幾個api就能模擬時間送進來了;當然,還有socket類的測試,管道什么的,,,)

            image

            3.3.2系統級交互(高階主題,主要是將在系統(如虛擬機)級別模擬外部操作)

             

            3.3.3高級交互

                    使用更高級抽象級別的事件流(或者腳本)來模擬外部操作。比如圖形程序的測試,以前是直接算坐標控制,現在用更聰明的手段(標識button的text,輸入指定的語句而不是裸的**_event)。簡而言之就是輸入更加具有邏輯性,更加接近“人工智能”

            image

             

            3.3.4 評估測試結果

                    不管是事件流還是通過用戶控件控制應用程序,都存在一個重要的問題:模擬環境必須檢查程序的輸出。

            ×必須通過檢查輸出進行同步,應為模擬用戶可能會一直等待直到一個特定的動作結束。

            ×必須通過檢查程序輸出來進行結果評估,測試的最終目的是確定結果是否和我們的預期相符。

                    表現層測試的優點是:它總能實現。我們總是可以模擬和自動執行用戶的行為。但是,這是唯一的優點。通常表現層測試只是用于:

            ×問題發生在表現層

            ×計算機程序可以很方便的調用表現層

            ×沒有其他的選擇(如:由于表現層和功能層沒有被清晰的分離,或者無法在較低層次上進行測試)

            界面對人越友好,它對計算機程序就越不友好。。。所以表現層測試應該不是最適合自動化測試的接口(至少對非表示層coder來說)

             

            3.4在功能層測試

                    相比較于模擬用戶交互,更加可取的方法是為程序設計一個適合于進行自動化的接口---或者通俗的說,設計接口時要考慮和測試系統的交互。比如通過提供腳本語言接口,腳本語言允許最終用戶或者測試人員通過簡單的方式自動執行某些任務。

                    在功能層進行測試的最大優點是:很容易獲取和評估結果。但是,這種測試的前提條件是能清晰的分離表現層和功能層。而一些陳舊的程序都是獨立的整體,沒有進行表現層和功能層的分離。這種情況下,有三種選擇:

            ×繼續在表現層惡心的測試,然后繼續糾結

            ×重新進行大幅度的重新設計,以分離表現層和功能層,或者至少減少他們之間的依賴關系

            ×分解程序,并且直接測試獨立的單元

             

            3.5在單元層測試

                    任何復雜的程度都可以分解成大量獨立的單元---子程序、函數、庫、模塊、抽象數據類型、對象、類、包、組建、beans或者設計方案和語言提供的任何分解機制。單元之間通過接口同學---就像程序之間通過他們所處的環境進行通信一樣。

                    現在的想法不是需要自動運行整個程序,而是自動運行某個特定的單元。其優點是自動運行分離的單元一般都比自動運行整個程序容易的多。當然,缺點是自能自動化某個特定的單元行為,于是必須考慮在分離單元的過程中引入的問題。

                    最終用戶通常是不能訪問單元的,因此不可能通過用戶腳本來執行系統的功能。但是,程序員可以使用外圍程序訪問服務的方式訪問單元(PS: 這句有點繞口,感覺是讓程序員自己去寫code做單元測試)

                    所有的單元測試工具都提供了一個能組織大量單獨測試用例的測試框架---每個測試覆蓋一個獨立的單元。單元測試應該能在沒有任何用戶交互的情況下自動運行,測試框架會按照要求運行部分或者所有的單元測試,然后概要顯示運行單元測試以及各自的輸出結果。運行某一個單元測試時,測試框架會按照以下三個步驟進行:

            ×建立單元測試以及運行的周邊環境。通常一個單元可能需要其他單元或者操作環境的服務。該步驟建立起能使測試運行的環境。

            ×執行單元測試。每個測試用例覆蓋該單元的一個可能的行為,用例首先執行所有操作,然后驗證輸出是否與預期相符。

            ×重新清理測試環境。

             

            3.6分離單元

                    有一些程序的功能層依賴于表現層,根本不可能把他們分離。比如print_to_file,把當前網頁打印到文件中。為了防止覆蓋已經存在的文件,會請求用戶確認是否已經存在。(這個其實也可以使用的代碼搞定,麻煩點,不過“確認”這個功能的測試就是必須UI和用戶參與)

            image

            ×表現層依賴功能層,應為他需要調用print_to_file()

            ×功能層依賴表現層,應為他需要調用confirm_loss()

            問題就來了:如何切斷依賴關系,使單元可以更好分離?

            對于這個例子處理起來比較容易。可以讓函數按照兩種方式運行:自動模式禁止用戶確認功能,總是返回true;交互模式,打開用戶確認功能,等待用戶回答。更加通用的方式是:參數化print_to_file函數,使他能與不同的表現層工作。

            image

            (PS:其實還可以通過引入一個中間層來解決,假設給print_to_file()加上參數,然后core不再依賴pressntation,而是依賴一個消息模塊、或者控制模塊,那么只要寫一個模擬發送消息、模擬控制的模塊即可。解決循環依賴直接的辦法是引入中間層)

             

            3.7為調試而設計

                    依賴抽象而不是具象這一原則對于減少依賴關系有很大幫助。實際上可以利用這種方法創建整個應用程序框架,其中最流行的一個例子就是模型-視圖-控制器架構模式,該模式能從應用程序級上解除功能層和表現層之間的耦合。

            image

             

                    如何創建一個這樣的系統?最關鍵的還是分離功能層和表現層。我們決不希望核心功能依賴某個特定視圖。MVC模式就是解決這類問題的一個通用方案。他把職責分解為兩個部分:

            ×模型管理核心數據,并且提供處理這些核心數據的服務。

            ×個總觀察者注冊或者粘附(attach)在模型上,核心數據一旦發生變化,他們就會得到通知。

            觀察者又可以分成兩種類型:

            ×視圖負責以特定的方式顯示核心數據

            ×控制器負責處理輸入時間并調用模型服務

            用戶和控制器交互是,他最終可能會調用一個改變核心數據的服務。這是注冊在模型上的所有視圖都會得到通知。也就是說,他們能從模型那里獲得數據以及更新顯示。從而用戶也就得到反饋。

            MVC給測試和調試帶來的好處:對于測試來說可以創建和添加新的控制器來調用模型提供的服務---例如,能自動記錄執行這些服務的控制器。對于調試來說,可以支持特殊的視圖來記錄模型的所有變化。最后,可以單獨的檢查每一個觀察者和模型,減少復雜性。

            image

             

             

            3.8預防未知問題

            posted @ 2013-03-03 15:18 Enic 閱讀(267) | 評論 (0)編輯 收藏

            1 : VS2005的STL性能不佳,請改用新的編譯器測試,例如VS2010或VS2012或minGW4.7
            如果使用mingw,記得讓編譯器支持c++11。
            insert資料的時候善用emplace_back(可以保證就地construct,而非copy再construct)
            不過我用mingw4.6的時候,map和set似乎還不支援這項功能
            2 :  AVL樹可能和stl的map或set的資料結構不同(red black tree),雖然兩者很象啦
            http://bbs.csdn.net/topics/390369473?page=2
            posted @ 2013-02-26 13:21 Enic 閱讀(381) | 評論 (0)編輯 收藏

            ×少量的預防措施要比大量的治療措施有價值的多。。。

             

            1.故障從哪里來

            為了尋找有缺陷的代碼,你必須以這個故障作為起點回溯追蹤起因。

            1.2從缺陷到故障

            通常缺陷是通過以下四個階段產生的:

            1.程序員制造了一個缺陷:所有代碼都是程序員寫的,寫錯了。

            2.缺陷造成了錯誤狀態的感染:正確的代碼段,被錯誤的代碼感染。這時候代碼已經不可控。

            3.錯誤狀態不斷的傳播:大多數程序由于不正確的輸入而返回錯誤,當后面的程序訪問該狀態時,會把錯誤擴散到后續的程序狀態中。(正確情況應該是不會持續傳播的,應該會被后續某個模塊覆蓋或者修正)

            4.錯誤狀態引發的故障:外部程序應為感知到了程序的錯誤狀態而故障

            ×錯誤只能程序有缺陷,不能證明程序沒有缺陷。。。

             

            1.3迷失在時空之中

            調試過程可以分解成七個步驟:

            1.track the problem

            2.reproduce the failure

            3.automate and simplify

            4.find infection origins

            5.focus on likely origins

            6.isolate the infection chain

            7.correct the defect

             

            在很大程度上,調試就是一個搜索問題,主要是如下兩個原則:

            ×從錯誤狀態中分離出正確狀態:如果一個狀態是錯誤的,它可能就是從缺陷到故障的傳播鏈中的一部分;如果一個狀態是正確的,他就基本不可能有錯誤被傳播。

            ×從不相關狀態中分離出相關狀態:一個變量的值取決于一小部分早期變量的值。因此,只有一部分早期狀態是和程序故障相關的。

             

            1.4從故障到修正

            ×跟蹤問題:

            ×重現故障:

            ×自動化和簡化測試用例:如果是一個復雜的程序,就必須考慮如何自動產生故障(應為希望被重現),以及如何簡化輸入,得到最小測試用例。

            ×尋找可能的感染源:如果有自動化測試可以使用排除法,將測試數據中會導致錯誤的數據找到。

            ×分離感染源:假設找到是某個測試數據導致錯誤,現在可以回溯相關系統這個數據出來的模塊。

            ×修正缺陷:

             

            1.5自動調試技術

            ×簡化輸入:

            ×程序片段:

            ×觀察狀態:

            ×監視狀態:

            ×斷言:

            ×反常:

            ×因果鏈:

             

            1.6 BUG、失誤、還是缺陷

            缺陷(defect):錯誤的程序代碼(代碼中的bug)

            錯誤的狀態感染(infection): 錯誤的程序狀態(狀態中的bug)

            故障(failure): 可感知程序的錯誤行為(行為中的bug)

             

            summary:

            1.調試程序的七個步驟:跟蹤->重現->自動化->發現感染源->重點關注->分離->修正

            咱們平常就是自動化和分離的時候會偷懶,老實說,在調試復雜程序的時候,花點時間做自動化和分離是“磨刀不誤砍柴功”

             

            ////////////////////////////////////////////////////////////////////////////////////////////////

                    程序員寫了一段有缺陷的代碼,這是否意味著他犯了過錯呢?考慮這些情況:

            原始需求沒有預測到未來的變化,如:千年蟲

            只有當程序的某種行為呈現在用戶面前是時,才有可能被列入“故障”

            在模塊化的程序中,故障可能是由兩個模塊之間的不兼容接口造成的。

            分布式系統中,故障可能是由幾個組件之間無法預測的交互造成的

            。。。。。。

            這時候討論責任已然是一種政治態度

            ////////////////////////////////////////////////////////////////////////////////////////////////

             

            ////////////////////////////////////////////////////////////////////////////////////////////////

            /////  f16的bug

            image

            ////////////////////////////////////////////////////////////////////////////////////////////////

            image

            ////////////////////////////////////////////////////////////////////////////////////////////////

            posted @ 2013-02-23 14:58 Enic 閱讀(381) | 評論 (0)編輯 收藏

            final 修飾 class member just like const in c++;

            synchronized means thread safe

             

            final 修飾成員變量相當于cpp中的const修飾

            synchronized 相當于是聲明原子操作,同一個對象的不同synchronized語句塊是線程安全的,是synchrony的,,,

            posted @ 2013-02-23 14:49 Enic 閱讀(229) | 評論 (0)編輯 收藏

            渲染 渲染緩存 混合 像素格式混合 基礎渲染器 頂點源 路徑存儲器
            渲染器:渲染器負責表現“掃描線”中的每個線段。在渲染器之前AGG圖形中的線段
            是沒有顏色值的,只是位置、長度、和透明度。渲染器賦予線段色彩,最終成為一副
            完整的圖像。
            最常用的如下:像素格式渲染器-PixelFormatRenderer、基礎渲染器-BaseRender、掃描線(抗鋸齒)ScanlineRenderer渲染器 
            像素格式渲染器可以直接工作
            基礎渲染器需要像素格式作為模版支持
            掃描渲染器需要基礎渲染器作為模版支持
            渲染緩存:渲染緩存保存著一個個像素,作為AGG的畫布。它僅僅是一個內存塊,用來存儲像素,
            不提供任何繪圖功能,只允許你讀取和修改里邊的數據。它也不告訴你里邊的像素類型---它只管理內存
            混合器:混合器是用來處理不同像素格式的如:agg::rgba  agg::argb(PS:也許叫像素點混合器比較合適)
            像素格式混合器:如agg::pixfmt_rgb24。(像素塊混合器?)像素格式混合器的作用是直接操作像素,也就是
            在緩存里邊保持的數據。像素格式有兩個屬性決定:混合器類型(RGBA32)和順序(ORDER_ARGB)
            基礎渲染器:基礎渲染器是掃描線渲染器的基礎。基礎渲染器需要手動以模版的形式系統像素格式信息,
            他會通過像素格式混合器來渲染。(實際通過模版傳入的好像是像素格式混合器)他的功能比像素格式混合器來的
            要更全面一點,有更多的渲染接口。
            頂點源:頂點源是一個concept,有rewind()和vertex()函數。

            ********************
            參考教程
            http://www.360doc.com/content/12/0722/09/992979_225748412.shtml

            posted @ 2013-02-20 14:56 Enic 閱讀(269) | 評論 (0)編輯 收藏

            僅列出標題
            共22頁: First 14 15 16 17 18 19 20 21 22 
            日韩精品久久久久久| 久久精品国产99久久久| 日韩欧美亚洲综合久久影院d3| 亚洲国产精品一区二区久久hs| 久久亚洲中文字幕精品一区| 欧美粉嫩小泬久久久久久久| 久久国产精品免费一区| 久久嫩草影院免费看夜色| 久久国产成人精品国产成人亚洲| 国产精品久久久99| 久久夜色精品国产亚洲av| 久久久久久免费视频| 亚洲欧美日韩久久精品第一区| 天堂久久天堂AV色综合| 97久久超碰成人精品网站| 亚洲狠狠久久综合一区77777| 国产精品久久久久乳精品爆| 久久精品国产福利国产琪琪| 亚洲午夜精品久久久久久浪潮| 久久无码国产专区精品| 韩国免费A级毛片久久| 91久久精品国产成人久久| 四虎国产精品免费久久| 99久久夜色精品国产网站 | 精品人妻伦九区久久AAA片69| 性做久久久久久久久| 狠狠精品久久久无码中文字幕| 激情伊人五月天久久综合| 久久精品女人天堂AV麻| 亚洲精品蜜桃久久久久久| 欧美精品一区二区精品久久| 日韩va亚洲va欧美va久久| 99精品久久精品一区二区| 久久噜噜久久久精品66| 亚洲中文精品久久久久久不卡| 日本久久久精品中文字幕| 久久久久久国产精品无码下载| 狠狠色噜噜狠狠狠狠狠色综合久久| 国产精品欧美久久久久天天影视| 色综合久久无码中文字幕| 久久精品无码免费不卡|