青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Error

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

#

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

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

// learn_boost_asio.cpp : 定義控制臺應(yīng)用程序的入口點。
//
#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 閱讀(812) | 評論 (0)編輯 收藏

從GameDemo.cpp看起

 

1回顧通常的sdk窗口程序流程:注冊窗口-創(chuàng)建窗口-顯示窗口-啟動消息循環(huán)

 

1.1注冊窗口類

Duilib中最平凡的真實窗口類是:CWindowWnd,關(guān)于窗口注冊提供了兩個函數(shù),嚴(yán)格的說應(yīng)該是幾個:

RegisterWindowClass()

RegisterSuperclass()

GetWindowClassName()

GetSuperClassName()

GetClassStyle()

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

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

1.2創(chuàng)建窗口

    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接口用于創(chuàng)建窗口,同事注冊窗口類也通過虛函數(shù)的方式延后到子類實現(xiàn),super機(jī)制(如果有super優(yōu)先注冊)也帶進(jìn)來。

    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消息循環(huán)

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消息回調(diào)函數(shù)

在窗口類注冊的時候應(yīng)該要注冊窗口回調(diào)函數(shù)指針,Duilib中默認(rèn)是在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的一個靜態(tài)成員,這個函數(shù)值得看一下:

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這個消息有一個管用技巧,先復(fù)習(xí)下這個消息:

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

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

還有WM_NCDESTROY這個特殊的消息。

當(dāng)然了,還有這個牛逼的戲法:

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

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

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

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

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

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

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

    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 閱讀(2261) | 評論 (0)編輯 收藏

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

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

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

用link做,輕輕松松

nobody(1575393351) 10:13:40

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

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

他已經(jīng)發(fā)請求了

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

可以不加鎖

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

用link做,真心不用加鎖

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

不過必須用cas

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

CAS是啥

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

否則做不了多線程的并發(fā)

nobody(1575393351) 10:14:13

link是什么東西

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

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

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

會把問題復(fù)雜化

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

有簡單的辦法

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

但性能很好的

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

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

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

這樣可以避免很多麻煩

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

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

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

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

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

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

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

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

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

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

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

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

析構(gòu)也類似

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

性質(zhì)上和你在別的線程進(jìn)行了野指針操作沒有區(qū)別

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

ooseven(147340642) 10:32:31

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

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

reference counting嘛

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

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

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

現(xiàn)在流行

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

析構(gòu)的時候

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

肯定是所有shared_ptr都完蛋了

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

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

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

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

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

不僅僅是null的判斷吧

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

循環(huán)隊列里邊

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

tail->next == head

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

貌似這樣的

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

循環(huán)隊列?

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

ring

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

buffer

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

ringbuffer是另一個概念= =

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

囧,我錯了

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

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

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

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

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

= = 堆棧這么做是找死啊

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

就是算法有問題

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

我覺得這個例子有問題

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

你每一次push新數(shù)據(jù)進(jìn)去的時候

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

你的系統(tǒng)先把10Wtps過了,再說并發(fā)

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

都不能重用節(jié)點

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

都必須new一個新的

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

vczh四號粉絲(342775210)  10:37:57
你的系統(tǒng)先把10Wtps過了,再說并發(fā)
噗,我的服務(wù)端是單進(jìn)程多線程模型

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

客戶端才在搞多線程

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

說錯了

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

服務(wù)端是單線程多金正

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

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

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

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

小老鼠(273245994) 10:41:25

沈陽發(fā)生爆炸了

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

結(jié)果性能還可以

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

什么爆炸

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

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

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

很久很久很久以前寫的

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

然后寫這個的時候不知道m(xù)em barrier

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

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

小老鼠(273245994) 10:43:21

9時,太原街地下通道

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

當(dāng)時還問了這兩位將近一天……

小老鼠(273245994) 10:43:46

附近1公里都有震感

小老鼠(273245994) 10:43:57

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

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

牛逼

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

兩·會就不讓他們好好開

 

小老鼠(273245994) 10:43:57

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

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

牛逼

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

兩·會就不讓他們好好開

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

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

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

又黑人

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

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

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

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

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

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

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

只是我人肉翻譯了下而已

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

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

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

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

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

帖子?

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

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

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

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

看過就能說兩句

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

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

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

還見鬼了

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

??

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

我曾經(jīng)面試一個 剛畢業(yè)的小伙子,也談不上多優(yōu)秀

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

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

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

剛畢業(yè)的小伙子

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

還不是linked-list

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

自己想出來了?

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

是deque的

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

自己肯定想不出來,但已經(jīng)摸到邊了啊,我稍微誘導(dǎo)了一下

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

就出來了

vczh.Isotope(75497789) 10:49:27

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

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

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

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

復(fù)雜一點的數(shù)據(jù)結(jié)構(gòu)可能需要

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

至少隊列不需要啊= =

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

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

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

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

vczh.Isotope(75497789) 10:50:44

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

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

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

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

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

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

小老鼠(273245994) 10:52:15

內(nèi)傷了

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

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

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

ACM毒害人

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

做ACM踢掉(逃

質(zhì)量最大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

用了原子指令 

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

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

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

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

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

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

做acm題還是不錯的

Sean(123983971) 10:55:15

小矩形可以重疊嗎?

vczh.Konobuta(450635425) 10:55:16

實際上還是相當(dāng)于加鎖,只是粒度更小 

vczh.Konobuta(450635425) 10:55:32

就怕有的平臺不支持 

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

不支持CAS的平臺

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

等你學(xué)會編程之后

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

早就消失了

vczh.Konobuta(450635425) 10:54:05

用了原子指令 

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

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

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

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

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

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

做acm題還是不錯的

Sean(123983971) 10:55:15

小矩形可以重疊嗎?

vczh.Konobuta(450635425) 10:55:16

實際上還是相當(dāng)于加鎖,只是粒度更小 

vczh.Konobuta(450635425) 10:55:32

就怕有的平臺不支持 

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

不支持CAS的平臺

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

等你學(xué)會編程之后

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

早就消失了

vczh.Konobuta(450635425) 10:56:40

萬一有呢? 

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

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

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

連ARM都支持

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

就是沒有

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

不支持沒法辦事

VCZH.粉絲數(shù)組[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,你是沒有任何辦法的

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

不支持CAS的設(shè)備一般就是單核設(shè)備了吧

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

沒有CAS,同步只能

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

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

vczh.Ismeow(65200296) 10:58:52

不支持CAS的設(shè)備一般是不支持多任務(wù)的設(shè)備……

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

用中斷做分時任務(wù)是OK的

vczh.Ismeow(65200296) 10:59:27

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

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

多核 多中斷

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

就sb了

vczh.Ismeow(65200296) 10:59:56

你做個什么調(diào)度就爆了

VCZH.粉絲數(shù)組[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

只能踩死

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

vczh

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

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

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

你不是早就做了嗎

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

我什么時候大規(guī)模做過可商業(yè)化的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

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


教我

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

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

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

不是萌妹紙,滾!

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

不是萌妹紙,滾!

vczh.Konobuta(450635425) 11:07:11

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

話說回來

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

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

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

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

 

 

 

暫時的理解:

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


posted @ 2013-03-04 11:14 Enic 閱讀(1524) | 評論 (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 閱讀(310) | 評論 (0)編輯 收藏

3.1調(diào)試測試

×我們必須創(chuàng)建測試以重現(xiàn)問題

×我們必須多次運(yùn)行測試以簡化問題

×我們必須重新運(yùn)行測試以觀察運(yùn)行過程

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

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

在調(diào)試過程中需要頻繁的進(jìn)行自動測試,應(yīng)此最好盡可能的采用自動化測試。通常通過使用自動化測試技術(shù),可以更容易的進(jìn)行全面測試,自動化測試的好處在于:

×可以重用已有測試

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

×重復(fù)測試

×增強(qiáng)對軟件的信心

 

3.2控制程序

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

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

×表現(xiàn)層處理和用戶(或者構(gòu)建程序環(huán)境的任何事物)之間的交互

×功能層封裝程序的實際功能,功能獨立于表現(xiàn)層

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

image

 

 

3.3在表現(xiàn)層測試

3.3.1低級交互

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

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

image

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

 

3.3.3高級交互

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

image

 

3.3.4 評估測試結(jié)果

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

×必須通過檢查輸出進(jìn)行同步,應(yīng)為模擬用戶可能會一直等待直到一個特定的動作結(jié)束。

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

        表現(xiàn)層測試的優(yōu)點是:它總能實現(xiàn)。我們總是可以模擬和自動執(zhí)行用戶的行為。但是,這是唯一的優(yōu)點。通常表現(xiàn)層測試只是用于:

×問題發(fā)生在表現(xiàn)層

×計算機(jī)程序可以很方便的調(diào)用表現(xiàn)層

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

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

 

3.4在功能層測試

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

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

×繼續(xù)在表現(xiàn)層惡心的測試,然后繼續(xù)糾結(jié)

×重新進(jìn)行大幅度的重新設(shè)計,以分離表現(xiàn)層和功能層,或者至少減少他們之間的依賴關(guān)系

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

 

3.5在單元層測試

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

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

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

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

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

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

×重新清理測試環(huán)境。

 

3.6分離單元

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

image

×表現(xiàn)層依賴功能層,應(yīng)為他需要調(diào)用print_to_file()

×功能層依賴表現(xiàn)層,應(yīng)為他需要調(diào)用confirm_loss()

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

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

image

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

 

3.7為調(diào)試而設(shè)計

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

image

 

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

×模型管理核心數(shù)據(jù),并且提供處理這些核心數(shù)據(jù)的服務(wù)。

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

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

×視圖負(fù)責(zé)以特定的方式顯示核心數(shù)據(jù)

×控制器負(fù)責(zé)處理輸入時間并調(diào)用模型服務(wù)

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

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

image

 

 

3.8預(yù)防未知問題

posted @ 2013-03-03 15:18 Enic 閱讀(279) | 評論 (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的資料結(jié)構(gòu)不同(red black tree),雖然兩者很象啦
http://bbs.csdn.net/topics/390369473?page=2
posted @ 2013-02-26 13:21 Enic 閱讀(409) | 評論 (0)編輯 收藏

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

 

1.故障從哪里來

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

1.2從缺陷到故障

通常缺陷是通過以下四個階段產(chǎn)生的:

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

2.缺陷造成了錯誤狀態(tài)的感染:正確的代碼段,被錯誤的代碼感染。這時候代碼已經(jīng)不可控。

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

4.錯誤狀態(tài)引發(fā)的故障:外部程序應(yīng)為感知到了程序的錯誤狀態(tài)而故障

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

 

1.3迷失在時空之中

調(diào)試過程可以分解成七個步驟:

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

 

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

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

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

 

1.4從故障到修正

×跟蹤問題:

×重現(xiàn)故障:

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

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

×分離感染源:假設(shè)找到是某個測試數(shù)據(jù)導(dǎo)致錯誤,現(xiàn)在可以回溯相關(guān)系統(tǒng)這個數(shù)據(jù)出來的模塊。

×修正缺陷:

 

1.5自動調(diào)試技術(shù)

×簡化輸入:

×程序片段:

×觀察狀態(tài):

×監(jiān)視狀態(tài):

×斷言:

×反常:

×因果鏈:

 

1.6 BUG、失誤、還是缺陷

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

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

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

 

summary:

1.調(diào)試程序的七個步驟:跟蹤->重現(xiàn)->自動化->發(fā)現(xiàn)感染源->重點關(guān)注->分離->修正

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

 

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

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

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

只有當(dāng)程序的某種行為呈現(xiàn)在用戶面前是時,才有可能被列入“故障”

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

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

。。。。。。

這時候討論責(zé)任已然是一種政治態(tài)度

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

 

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

/////  f16的bug

image

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

image

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

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

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

synchronized means thread safe

 

final 修飾成員變量相當(dāng)于cpp中的const修飾

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

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

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

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

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

僅列出標(biāo)題
共22頁: First 14 15 16 17 18 19 20 21 22 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
              午夜精品美女久久久久av福利| 欧美中文字幕视频| 91久久午夜| 最新亚洲激情| 日韩视频在线免费观看| 亚洲精品一区二| 99re热这里只有精品视频| 99精品热视频只有精品10| 在线亚洲伦理| 亚洲欧美日韩成人高清在线一区| 午夜日韩电影| 久久精品色图| 欧美成人午夜免费视在线看片| 欧美激情91| 亚洲精品美女在线观看| 91久久精品国产91久久性色tv | 中文在线一区| 亚洲一级高清| 久久av一区二区三区| 久久久综合激的五月天| 欧美激情乱人伦| 欧美日韩在线另类| 国产九九精品视频| 伊人成人在线视频| 亚洲精选成人| 欧美一级午夜免费电影| 麻豆精品视频在线| 亚洲欧洲一区二区在线播放 | 欧美成人精品在线视频| 欧美激情小视频| 在线综合+亚洲+欧美中文字幕| 小处雏高清一区二区三区| 美女被久久久| 欧美涩涩网站| 伊人久久亚洲热| 这里只有精品电影| 久久久噜噜噜久噜久久| 亚洲国产裸拍裸体视频在线观看乱了| 一区二区三区偷拍| 久久久综合网站| 国产精品久久久99| 亚洲丶国产丶欧美一区二区三区 | 免费成年人欧美视频| 亚洲毛片一区二区| 久久精品一二三区| 国产精品av久久久久久麻豆网| 激情欧美一区二区| 亚洲天堂av电影| 欧美阿v一级看视频| 亚洲视频在线观看一区| 免费高清在线一区| 国产欧美日韩三区| 在线视频欧美精品| 卡通动漫国产精品| 亚洲永久免费| 欧美喷水视频| 亚洲动漫精品| 久久国产日韩| 亚洲私人影院在线观看| 免费久久精品视频| 国产综合色在线视频区| 亚洲一区自拍| 亚洲精品在线电影| 久久久在线视频| 国产一区二区电影在线观看 | 亚洲精品久久久久久久久| 久久er精品视频| 国产精品久久久一区麻豆最新章节| 亚洲日本欧美| 免费成人高清| 久久riav二区三区| 国产麻豆精品久久一二三| 亚洲网站视频福利| 91久久精品www人人做人人爽| 久久天天狠狠| 国产午夜久久| 欧美影视一区| 亚洲一区成人| 国产精品国产三级欧美二区| aa国产精品| 亚洲国产人成综合网站| 免费精品视频| 亚洲国产婷婷香蕉久久久久久| 久久一区亚洲| 久久国产精品99久久久久久老狼| 国产精品尤物| 香蕉乱码成人久久天堂爱免费| 一区二区三区欧美在线观看| 欧美日韩mp4| 一本色道久久综合亚洲精品按摩| 亚洲国产欧美在线| 欧美成ee人免费视频| 亚洲韩日在线| 欧美高清视频www夜色资源网| 久久免费观看视频| 亚洲承认在线| 亚洲高清一区二区三区| 欧美高清视频在线| 亚洲精品在线三区| 亚洲精品黄网在线观看| 欧美理论电影网| 中文在线不卡视频| 99视频精品在线| 国产精品xxxav免费视频| 亚洲午夜精品一区二区三区他趣| 亚洲作爱视频| 国产精品美女久久久久久免费 | 午夜影院日韩| 国产日韩一区| 久久在线精品| 你懂的国产精品永久在线| 亚洲精品在线观| 亚洲精品综合| 国产精品久久久久久一区二区三区| 香蕉久久夜色精品国产| 欧美在线资源| 亚洲人永久免费| 亚洲乱码国产乱码精品精天堂| 国产精品99一区| 欧美综合第一页| 久久久久综合网| 999亚洲国产精| 亚洲伊人久久综合| 韩国精品久久久999| 欧美黄色精品| 国产精品国产一区二区| 久久久精彩视频| 欧美岛国在线观看| 香蕉成人伊视频在线观看| 久久精品国产免费观看| 日韩午夜av电影| 亚洲一区二区三区涩| 一区二区三区中文在线观看 | 久久高清国产| 亚洲精品乱码| 亚洲免费在线精品一区| 在线免费观看一区二区三区| 亚洲精品一区二区三区不| 国产精品一区二区在线观看不卡| 免费观看久久久4p| 欧美日韩中文字幕在线视频| 欧美永久精品| 欧美激情精品久久久久久黑人| 销魂美女一区二区三区视频在线| 久久久久久9999| 亚洲性视频h| 久久久久久有精品国产| 亚洲一区二区高清| 久久免费视频观看| 亚洲伊人伊色伊影伊综合网 | 亚洲高清在线| 在线视频中文亚洲| 亚洲国产精品福利| 亚洲欧美三级在线| 亚洲免费观看| 久久久久91| 欧美亚洲一区| 欧美国产精品中文字幕| 久久久久久久久久看片| 欧美特黄a级高清免费大片a级| 蜜臀av一级做a爰片久久| 国产精品麻豆欧美日韩ww| 亚洲二区视频在线| 国内精品一区二区三区| 一本色道久久综合| 亚洲黄色性网站| 久久精品导航| 性欧美激情精品| 欧美日韩国产在线播放| 欧美成人国产| 国内成人精品视频| 亚洲欧美国产不卡| 一片黄亚洲嫩模| 欧美成人免费网站| 久久综合中文字幕| 国产欧美大片| 亚洲一区二区在线免费观看| 一区二区欧美精品| 蜜桃久久av| 欧美α欧美αv大片| 国内外成人在线| 欧美一区=区| 欧美在线三级| 国产精品一区二区黑丝| 亚洲少妇一区| 亚洲一区三区电影在线观看| 欧美精品乱码久久久久久按摩| 欧美国产日本高清在线| 一区二区三区在线高清| 欧美在线三区| 久久久一本精品99久久精品66| 国产欧美精品日韩区二区麻豆天美| 在线亚洲+欧美+日本专区| 99天天综合性| 欧美日韩精品| 日韩亚洲欧美一区二区三区| 亚洲作爱视频| 欧美日韩国产成人在线观看| 亚洲精品日产精品乱码不卡| 99精品视频网|