• <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>
            posts - 13, comments - 4, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            Imperfect C++ 讀書筆記(二)

            Posted on 2008-11-19 00:14 Batiliu 閱讀(506) 評論(0)  編輯 收藏 引用 所屬分類: 讀書筆記

            可移植的虛函數(shù)表

            C++并非一門合適的模塊——接口語言,為了支持ABI/OAB(Application Binary Interface/Objects Across Borders)需要付出相當(dāng)程度的努力,并且使用者還必須受到嚴(yán)格的約束。下面介紹一種得到廣泛運(yùn)用的跨邊界對象技術(shù),如果你熟悉Win32 COM,肯定立馬心領(lǐng)神會。

             

            接口代碼:

            // Interface.h
            //
            struct IObject;
             
            struct IObjectVTable
            {
                void (*SetName)(struct IObject * obj, char const * s);
                char const * (*GetName)(struct IObject const * obj);
            };
             
            struct IObject
            {
                struct IObjectVTable * const vtable;
            #ifdef __cplusplus
            protected:
                IObject(struct IObjectVTable * vt)
                    : vtable(vt)
                {}
                ~IObject()
                {}
            public:
                inline void SetName(char const * s)
                {
                    assert(NULL != vtable);
                    vtable->SetName(this, s);
                }
                inline char const * GetName() const
                {
                    assert(NULL != vtable);
                    return vtable->GetName(this);
                }
            private:
                IObject(IObject const & rhs);
                IObject & operator=(IObject const & rhs);
            #endif    /* __cplusplus */
            };
             
            extern "C" IObject * createObject();
            extern "C" void destroyObject(IObject *);

             

            服務(wù)端代碼:

            // Server.cpp
            //
            class Object : public IObject
            {
            public:
                virtual void SetName(char const * s)
                {
                    m_name = s;
                }
                virtual char const * GetName() const
                {
                    return m_name.c_str();
                }
            #ifndef POAB_COMPILER_HAS_COMPATIBLE_VTABLES
            public:
                Object()
                    : IObject(GetVTable())
                {}
                Object(Object const & rhs)
                    : IObject(GetVTable())
                    , m_name(rhs.m_name)
                {}
            private:
                static void SetName_(IObject * this_, char const * s)
                {
                    static_cast<Object*>(this_)->SetName(s);
                }
                static char const * GetName_(IObject const * this_)
                {
                    return static_cast<Object const *>(this_)->GetName();
                }
                static IObjectVTable * GetVTable()
                {
                    static IObjectVTable s_vt = MakeVTable();
                    return &s_vt;
                }
                static IObjectVTable MakeVTable()
                {
                    IObjectVTable vt = { SetName_, GetName_ };
                    return vt;
                }
            #endif    /* !POAB_COMPILER_HAS_COMPATIBLE_VTABLES */
            private:
                std::string m_name;
            };

             

            客戶端代碼:

            // Client.cpp
            //
            int _tmain(int argc, _TCHAR* argv[])
            {
                IObject * pObj = createObject();
             
                pObj->SetName("Matthew Wilson");
             
                std::cout << "name: " << pObj->GetName() << std::endl;
             
                destroyObject(pObj);
             
                return 0;
            }

             

            synchronized關(guān)鍵字

            Java中有synchronized關(guān)鍵字,.NET中有l(wèi)ock關(guān)鍵字,它們可以被用于守護(hù)臨界區(qū)。而C++標(biāo)準(zhǔn)對線程幾乎只字未提,自然也沒有相關(guān)設(shè)施。而然借助一點(diǎn)點(diǎn)宏,我們就能輕松實(shí)現(xiàn)同樣的效果:(lock_scope請參考筆記(一)中的域守衛(wèi)類)

            #define SYNCHRONIZED_BEGIN(T, v) \
                { \
                    lock_scope<T> __lock__(v);
            #define SYNCHROIZED_END() \
                }

             

            如果你和我一樣不喜歡SYNCHROIZE_END()部分,畢竟和synchronized或lock比起來似乎不那么優(yōu)雅,那么可以用點(diǎn)小技巧,像這樣定義宏:

            #define synchronized(T, v) \
                for (synchronized_lock<lock_scope<T> > __lock__(v); \
                    __lock__; __lock__.end_loop())
             
            template<typename T>
            struct synchronized_lock : public T
            {
            public:
                template<typename U>
                synchronized_lock(U & u)
                    : T(u)
                    , m_bEnded(false)
                {}
                operator bool () const
                {
                    return !m_bEnded;
                }
                void end_loop()
                {
                    m_bEnded = true;
                }
            private:
                bool m_bEnded;
            };

            客戶代碼:

            synchronized(Object, obj)
            {
                ...    // 臨界區(qū)代碼
            }
             
                ...    // 非臨界區(qū)代碼
             
            synchronized(Object, obj)
            {
                ...    // 臨界區(qū)代碼
            }

             

            上述代碼,熟悉JAVA的朋友是不是很親切?不過還是有個小小的遺憾,那就是對象的類型不能被自動推導(dǎo)出來,導(dǎo)致我們必須手工提供兩個參數(shù)。

            這里還有個問題要注意,如果同一個作用域中出現(xiàn)了兩個同步段,某些老式編譯器(如大名鼎鼎的VC6.0)對for循環(huán)處理的不那么“標(biāo)準(zhǔn)”,就會報(bào)出“重新定義__lock__”的錯誤。所以作者對此提供了一個可移植的解決方案,來確保每個“__lock__”都是不一樣的:

            #define concat__(x, y) x ## y
            #define concat_(x, y) concat__(x, y)    // 用兩層宏來取__LINE__的實(shí)際值
            #define synchronized(T, v) \
                for (synchronized_lock<lock_scope<T> > concat_(__lock__,__LINE__)(v); \
                    concat_(__lock__,__LINE__); concat_(__lock__,__LINE__).end_loop())

            但是,作者似乎忘了,某些老式編譯器(如VC6.0)對循環(huán)變量的釋放,會延遲到整個作用域結(jié)束時,而不是臨界代碼段的右括號處。所以該解決方案是錯誤的!

             

            局部靜態(tài)對象

            函數(shù)局部靜態(tài)對象的初始化存在的固有的競爭條件是非常重要的問題。因此不能被忽略。然而,它同時也是非常罕見的情況。我們可以利用其罕見性,給出一個極其優(yōu)雅的解決方案,該解決方案基于自旋互斥體。自旋互斥體本身依賴于原子操作,它的開銷是非常低的。

            class spin_mutex
            {
            public:
                explicit spin_mutex(int * p = NULL)
                    : m_spinCount((NULL != p) ? p : &m_internalCount)
                    , m_internalCount(0)
                {}
                void lock()
                {
                    for (; 0 != atomic_write(m_spinCount, 1); sched_yield())
                    {}    // PTHREAD函數(shù)seched_yield()將執(zhí)行機(jī)會讓給其他線程
                }
                void unlock()
                {
                    atomic_set(m_spinCount, 0);
                }
            private:
                int * m_spinCount;
                int m_internalCount;
            private:
                spin_mutex(spin_mutex const & rhs);
                spin_mutex & operator=(spin_mutex const & rhs);
            };
             
            Local & GetLocal()
            {
                static int guard;         // 在加載期被初始化為0
                spin_mutex smx(&guard);             // 對guard進(jìn)行自旋
                lock_scope<spin_mutex> lock(smx);   // 使用smx來加鎖
             
                static Local local;
                return local;
            }
            亚洲成色999久久网站| 99久久免费国产特黄| 久久www免费人成精品香蕉| 精品久久久久久久久久中文字幕| 久久这里只有精品久久| 青春久久| 久久精品一区二区三区不卡| 精品久久久噜噜噜久久久| 亚洲色欲久久久综合网东京热 | 久久久国产亚洲精品| 欧美伊人久久大香线蕉综合| 国产婷婷成人久久Av免费高清| 久久播电影网| 国产婷婷成人久久Av免费高清| 久久久久久青草大香综合精品| 亚洲香蕉网久久综合影视| 99久久人人爽亚洲精品美女| 色综合久久无码中文字幕| 精品久久久久久无码中文野结衣| 亚洲av成人无码久久精品 | 一本色道久久88精品综合| AAA级久久久精品无码区| 久久精品国产亚洲精品2020| 伊人久久无码精品中文字幕| 久久综合久久久| 久久久精品午夜免费不卡| 少妇久久久久久被弄高潮| 日韩精品久久久久久久电影| 久久久久国色AV免费观看| 青青国产成人久久91网| 69久久夜色精品国产69| 精品国产乱码久久久久久郑州公司| 中文字幕人妻色偷偷久久| 欧美久久久久久| 久久久久久综合网天天| 一本久久a久久精品亚洲| 青青草原综合久久大伊人| 久久国产色av免费看| 无码人妻久久一区二区三区免费丨 | 狠狠色综合网站久久久久久久 | 精品久久久久中文字幕一区|