• <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

            #

            CMake Manual

            CMake is a tool that helps simplify the build process for development projects across different platforms. CMake automates the generation of buildsystems such as Makefiles.

            CMake is a 3rd party tool with its own documentation. The rest of this manual details the specifics of how to use Qt 5 with CMake. The minimum version required to use Qt5 is CMake 2.8.3, but 2.8.9 is recommended.

            Getting Started

            The first requirement when using CMake is to use find_package to locate the libraries and header files shipped with Qt. These libraries and header files can then be used to build libraries and applications based on Qt.

            The recommended way to use Qt libraries and headers with CMake 2.8.9 is to use the qt5_use_modules macro.

            To build a helloworld executable, typical usage would be:

            cmake_minimum_required(VERSION 2.8.9)
            
            project(testproject)
            
            # Find includes in corresponding build directories
            set(CMAKE_INCLUDE_CURRENT_DIR ON)
            # Instruct CMake to run moc automatically when needed.
            set(CMAKE_AUTOMOC ON)
            
            # Find the QtWidgets library
            find_package(Qt5Widgets)
            
            # Tell CMake to create the helloworld executable
            add_executable(helloworld main.cpp)
            
            # Use the Widgets module from Qt 5.
            qt5_use_modules(helloworld Widgets)

            Note that it is necessary to use find_package to find a Qt module before using the macro. See the documentation for the CMake find_package Documentation command for the full options it supports.

            In order for find_package to be successful, Qt 5 must be found below the CMAKE_PREFIX_PATH, or the Qt5<Module>_DIR must be set in the CMake cache to the location of the Qt5WidgetsConfig.cmake file. The easiest way to use CMake is to set the CMAKE_PREFIX_PATH environment variable to the install prefix of Qt 5.

            The qt5_use_modules macro encapsulates all of the variable usage required to use a Qt module. It automatically finds the modules given to it on the command line if they have not already been found.

            find_package(Qt5Core)
            
            # Find the Widgets Sql and Network modules, and
            # use them in helloworld.
            qt5_use_modules(helloworld Widgets Sql Network)

            The CMAKE_AUTOMOC setting runs moc automatically when required. For more on this feature see the CMake AUTOMOC documentation

            Imported targets

            Imported targets are created for each Qt module. That means that the Qt5<Module>_LIBRARIES contains a name of an imported target, rather than a path to a library. The actual path to the library can be obtained using the LOCATION property:

            find_package(Qt5Core)
            
            get_target_property(QtCore_location Qt5::Core LOCATION)

            Note however that it is rare to require the full location to the library in CMake code. Most CMake APIs are aware of imported targets and can automatically use them instead of the full path.

            Each module in Qt 5 has a library target with the naming convention Qt5::<Module> which can be used for this purpose.

            Imported targets are created with the configurations Qt was configured with. That is, if Qt was configured with the -debug switch, an imported target with the configuration DEBUG will be created. If Qt was configured with the -release switch an imported target with the configuration RELEASE will be created. If Qt was configured with the -debug-and-release switch (the default on windows), then imported targets will be created with both RELEASE and DEBUG configurations.

            If your project has custom CMake build configurations, it may be necessary to set a mapping from your custom configuration to either the debug or release Qt configuration.

            find_package(Qt5Core)
            
            set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage")
            
            # set up a mapping so that the Release configuration for the Qt imported target is
            # used in the COVERAGE CMake configuration.
            set_target_properties(Qt5::Core PROPERTIES MAP_IMPORTED_CONFIG_COVERAGE "RELEASE")
            Using Qt 5 with CMake older than 2.8.9

            If using CMake older than 2.8.9, the qt5_use_modules macro is not available. Attempting to use it will result in an error.

            To use Qt 5 with versions of CMake older than 2.8.9, it is necessary to use the target_link_libraries, include_directories, and add_definitions commands, and to manually specify moc requirements with either qt5_generate_moc or qt5_wrap_cpp:

            cmake_minimum_required(VERSION 2.8.3)
            
            project(testproject)
            
            # Find includes in corresponding build directories
            set(CMAKE_INCLUDE_CURRENT_DIR ON)
            
            # Find the QtWidgets library
            find_package(Qt5Widgets)
            
            # Add the include directories for the Qt 5 Widgets module to
            # the compile lines.
            include_directories(${Qt5Widgets_INCLUDE_DIRS})
            
            # Use the compile definitions defined in the Qt 5 Widgets module
            add_definitions(${Qt5Widgets_DEFINITIONS})
            
            # Add compiler flags for building executables (-fPIE)
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
            
            qt5_generate_moc(main.cpp main.moc)
            
            # Tell CMake to create the helloworld executable
            add_executable(helloworld main.cpp main.moc)
            
            #Link the helloworld executable to the Qt 5 widgets library.
            target_link_libraries(${Qt5Widgets_LIBRARIES})

            It is also necessary when using an older CMake to add Qt5<Module>_EXECUTABLE_COMPILE_FLAGS to the CMAKE_CXX_FLAGS so that the -fPIE flags are added to the compile flags if necessary (as is the default with Qt 5).

            If not using the qt5_use_modules macro, and if using CMake 2.8.9 or later, the POSITION_INDEPENDENT_CODE property can be set on targets using Qt instead, or it can be set globally for all targets:

            find_package(Qt5Core)
            
            add_executable(exe1 ${exe1_SRCS})
            # Set the POSITION_INDEPENDENT_CODE property for the exe1 target...
            set_target_properties(exe1 PROPERTIES POSITION_INDEPENDENT_CODE ON)
            
            # Or set it globally for all targets:
            set(CMAKE_POSITION_INDEPENDENT_CODE ON)
            add_executable(exe2 ${exe2_SRCS})
            
            add_executable(exe3 ${exe3_SRCS})

            Note that it may be necessary to enable POSITION_INDEPENDENT_CODE globally in order to use try_compile with Qt code, or any wrapper macros around it such as check_cxx_source_compiles etc. As position independent code is a platform-specific and Qt-configuration-specific concept, the Qt5_POSITION_INDEPENDENT_CODE property can be used to check whether it is required.

            if (Qt5_POSITION_INDEPENDENT_CODE)
              set(CMAKE_POSITION_INDEPENDENT_CODE ON)
            endif()

            Variable Reference

            Module variables

            The result of a find_package call is that some variables will be populated with information required to configure the build, and macros will be made available for use. All of the package-specific variables have a consistent name with a prefix of the name of the package. For example, find_package(Qt5Widgets) will make the following variables available if successfully found:

            • Qt5Widgets_VERSION_STRING
            • Qt5Widgets_LIBRARIES List of libraries for use with the target_link_libraries command, for example.
            • Qt5Widgets_INCLUDE_DIRS List of libraries for use with the include_directories command, for example.
            • Qt5Widgets_DEFINITIONS List of definitions for use with add_definitions, for example.
            • Qt5Widgets_COMPILE_DEFINITIONS List of definitions for use with the COMPILE_DEFINITIONS target property.
            • Qt5Widgets_FOUND Boolean describing whether the module was found successfully.
            • Qt5Widgets_EXECUTABLE_COMPILE_FLAGS String of flags to be used when building executables.

            Equivalents of those variables will be available for all packages found with a find_package call. Note that the variables are case-sensitive.

            Installation variables

            Additionally, several other variables are available which do not relate to a particular package, but to the Qt installation itself.

            • QT_VISIBILITY_AVAILABLE Boolean describing whether Qt was built with hidden visibility.
            • QT_LIBINFIX String containing the infix used in library names.

            Macro Reference

            Qt5Core macros

            Macros available when Qt5Core is found.

            Macro
            Description

            qt5_wrap_cpp(outfiles inputfile ... OPTIONS ...)
            Create moc code from a list of files containing Qt class with the Q_OBJECT declaration. Per-direcotry preprocessor definitions are also added. Options may be given to moc, such as those found when executing "moc -help".

            qt5_add_resources(outfiles inputfile ... OPTIONS ...)
            Create code from a list of Qt resource files. Options may be given to rcc, such as those found when executing "rcc -help"

            qt5_generate_moc(inputfile outputfile )
            Creates a rule to run moc on infile and create outfile. Use this if for some reason QT5_WRAP_CPP() isn't appropriate, e.g. because you need a custom filename for the moc file or something similar.

            qt5_use_modules(target [LINK_PUBLIC|LINK_PRIVATE] module ... )
            Indicates that the target uses the named Qt 5 modules. The target will be linked to the specified modules, use the include directories installed by those modules, use the COMPILE_DEFINITIONS set by those modules, and use the COMPILE_FLAGS set by the modules. The LINK_PRIVATE or LINK_PUBLIC specifiers can optionally be specified. If LINK_PRIVATE is specified then the modules are not made part of the link interface of the target. See the documentation for target_link_libraries for more information.

            Note that this macro is only available if using CMake 2.8.9 or later.

            Qt5Widgets macros

            Macros available when Qt5Widgets is found.

            Macro
            Description

            qt5_wrap_ui(outfiles inputfile ... OPTIONS ...)
            Create code from a list of Qt designer ui files. Options may be given to uic, such as those found when executing "uic -help"

            Qt5DBus macros

            Macros available when Qt5DBus is found.

            Macro
            Description

            qt5_add_dbus_interface(outfiles interface basename)
            Create a the interface header and implementation files with the given basename from the given interface xml file and add it to the list of sources

            qt5_add_dbus_interfaces(outfiles inputfile ... )
            Create the interface header and implementation files for all listed interface xml files the name will be automatically determined from the name of the xml file

            qt5_add_dbus_adaptor(outfiles xmlfile parentheader parentclassname [basename] [classname])
            Create a dbus adaptor (header and implementation file) from the xml file describing the interface, and add it to the list of sources. The adaptor forwards the calls to a parent class, defined in parentheader and named parentclassname. The name of the generated files will be <basename>adaptor.{cpp,h} where basename defaults to the basename of the xml file. If <classname> is provided, then it will be used as the classname of the adaptor itself.

            qt5_generate_dbus_interface( header [interfacename] OPTIONS ...)
            Generate the xml interface file from the given header. If the optional argument interfacename is omitted, the name of the interface file is constructed from the basename of the header with the suffix .xml appended. Options may be given to qdbuscpp2xml, such as those found when executing "qdbuscpp2xml --help"

            Qt5LinguistTools macros

            Macros available when Qt5LinguistTools is found.

            Macro
            Description

            qt5_create_translation( qm_files directories ... sources ... ts_files ... OPTIONS ...)
            Out: qm_files In: Directories sources ts_files Options: flags to pass to lupdate, such as -extensions to specify Extensions for a directory scan. Generates commands to create .ts (vie lupdate) and .qm (via lrelease) - files from directories and/or sources. The ts files are created and/or updated in the source tree (unless given with full paths). The qm files are generated in the build tree. Updating the translations can be done by adding the qm_files to the source list of your library/executable, so they are always updated, or by adding a custom target to control when they get updated/generated.

            qt5_add_translation( qm_files ts_files ... )
            Out: qm_files In: ts_files Generates commands to create .qm from .ts - files. The generated filenames can be found in qm_files. The ts_files must exists and are not updated in any way.

            posted @ 2013-04-13 20:42 Enic 閱讀(1025) | 評論 (0)編輯 收藏

            更新到QT5以后發現CMAKE里邊的幾個函數變了,加上qt自身也做了一些調整,總之以前qt4下面用CMAKE編譯qt工程的那一套不管用了。

             

            然后在按照官方文檔寫了cmake嘗試編譯,發現報錯:

            http://qt-project.org/doc/qt-5.0/qtdoc/cmake-manual.html

            CMake Warning at CMakeLists.txt:5 (FIND_PACKAGE):
              By not providing "FindQt5Widgets.cmake" in CMAKE_MODULE_PATH this project
              has asked CMake to find a package configuration file provided by
              "Qt5Widgets", but CMake did not find one.

              Could not find a package configuration file provided by "Qt5Widgets" with
              any of the following names:

                Qt5WidgetsConfig.cmake
                qt5widgets-config.cmake

              Add the installation prefix of "Qt5Widgets" to CMAKE_PREFIX_PATH or set
              "Qt5Widgets_DIR" to a directory containing one of the above files.  If
              "Qt5Widgets" provides a separate development package or SDK, be sure it has
              been installed.

             

             

            百度了一下,中文基本找不到答案,Google了一下找到答案了,但是該死的我忽略了,后來自己整明白才發現人家給的是完全正確的答案。

            http://stackoverflow.com/questions/15639781/how-to-find-qt5-cmake-module-on-windows

             

             

            我的分析過程如下:

            根據錯誤,可以知道是找不到*Qt5*.cmake這些文件,觀察cmake安裝目錄自帶的一組*.cmake,確實沒有這些qt5工程編譯依賴的*.cmake,于是第一反應是想qt sdk代碼里邊一定是提供了的。去搜索一下,果不其然,,,

            直接拷貝過去了,,,發現問題依舊,,,不過這次提示的*.cmake內部的錯誤,初步分析了一下和目錄結構可能有點關系,,,這時候突然回憶起來上面給出的stackoverflow的帖子,,,

             

            果然設置一下

            CMAKE_PREFIX_PATH到qtbase目錄,就搞定

             

            初略的過了下cmake的文檔,在find_package中提到

            1. Search paths specified in cmake-specific cache variables. These are intended to be used on the command line with a -DVAR=value. This can be skipped if NO_CMAKE_PATH is passed.

               CMAKE_PREFIX_PATH
            CMAKE_FRAMEWORK_PATH
            CMAKE_APPBUNDLE_PATH
            posted @ 2013-04-13 20:39 Enic 閱讀(22211) | 評論 (1)編輯 收藏

            搞了搞split,發現boost里邊已經有了,就拿過來直接用,之前翻了下facebook的,也沒見比boost更容易讀,還是boost算了。
            在vs2012上編譯了一下,發現有問題:error C4996: 'std::_Copy_impl': Function call with para

            找了下,老外是這么說的:http://stackoverflow.com/questions/14141476/warning-with-boostsplit-when-compiling

            You haven't done anything wrong. Visual Studio is being overly cautious. In debug mode, visual studio uses something called "Checked Iterators". Pointers are also iterators, but the checking mechanism doesn't work with them. So when a standard library algorithm is called with pointers, which is something that boost::split does, it issues this warning.

            You'll get the same warning with this obviously safe code:

            int main()
            {
                int x[10] = {};
                int y[10] = {};
                int *a = x, *b = y;
                std::copy(a, a+10, b);
            }

            Disable the warning. It's for beginners. It's on by default for the safety of beginners, because if it was off by default, they wouldn't know how to turn it on.





            #include <boost/algorithm/string/classification.hpp>
            #include <boost/algorithm/string.hpp>
            void LearnSplit()
            {
                std::string strTem("1,2,3,4");
                std::list<std::string> listStrTem;
                std::vector<std::string> vectorStrTem;
                boost::split(listStrTem, strTem, boost::is_any_of(","));
                boost::split(vectorStrTem, strTem, boost::is_any_of(","));
                for(auto item : listStrTem)
                {
                    std::cout << item.c_str() << std::endl;
                }
                std::string s = "Hello, the beautiful world!";
                std::vector<std::string> rs;
                boost::split( rs, s, boost::is_any_of( " ,!" ), boost::token_compress_on );
            }
            int _tmain(int argc, _TCHAR* argv[])
            {
                LearnSplit();
            return 0;
            }
            posted @ 2013-04-11 00:29 Enic 閱讀(1058) | 評論 (0)編輯 收藏

            # for project: QSql
            # author: enic
            FILE(GLOB val_Tem models/*.h)
            SET(val_Inc ${val_Tem})
            FILE(GLOB val_Tem kernel/*.h)
            LIST(APPEND val_Inc ${val_Tem})
            FILE(GLOB val_Tem models/*.cpp)
            SET(val_Src ${val_Tem})
            FILE(GLOB val_Src kernel/*.cpp)
            LIST(APPEND val_Src ${val_Tem})
            SET(val_AllCode ${val_Inc} ${val_Src})
            ADD_LIBRARY(QSql SHARED ${val_AllCode})


            // code
            #include <QtSql>
            #include <iostream>
            bool Test_Qt_Sqlite()
            {
                QSqlDatabase dbConn = QSqlDatabase::addDatabase("QSQLITE");
                std::string strDatabaseName("sqlite.db");
                dbConn.setDatabaseName(strDatabaseName.c_str());
                if(!dbConn.open())
                {
                    std::cout << "db not opened" << std::endl;
                }
                
                QSqlQuery queryTest;
                std::string strCreateTable("create table student(id varchar, name varchar)");
                queryTest.exec(strCreateTable.c_str());
                std::string strInsert("intert into student values(1, '狗仔')");
                return false;
            }

            ////////////////
            qsqlquery似乎不需要指定connection,莫非全部在底層搞了,這樣如果需要多個sql connection怎么辦,,,還是看源碼吧,qt確實很多東東不到位啊
            posted @ 2013-04-09 23:43 Enic 閱讀(207) | 評論 (0)編輯 收藏

            // filename: CEIocpSocket.cpp
            // author: enic
            // date: 2013-03-30

            #include "CEIocpSocket.h"

            #include "CESpinLock.h"

            HANDLE CEIocpSocket::ms_hIoComplete = NULL;

            CEIocpSocket::~CEIocpSocket()
            {
            }

             

             

             

             

             

             


            E_DWORD CEIocpSocket::InitIocpWorkThreads()
            {
                if (ms_hIoComplete != false)
                {
                    return E_ERR;
                }

                SYSTEM_INFO nativeSysInfo;
                ::GetNativeSystemInfo(&nativeSysInfo);

                E_SIZE nThreadNum = nativeSysInfo.dwNumberOfProcessors*2;

                ms_hIoComplete = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, nThreadNum);
                Thread_EIocpSocket_StartParameter startParameter;
                memset(&startParameter, NULL, sizeof(startParameter));
                startParameter.hIoComplete = ms_hIoComplete;

                for (E_SIZE n = 0; n < nThreadNum; ++n)
                {
                    boost::thread newThread(
                        boost::bind(&CEIocpSocket::Thread_EIocpSocket, startParameter));

                    EIOCP_OVERLAPPED* pIocpOverlapped = new EIOCP_OVERLAPPED;
                    memset(pIocpOverlapped, NULL, sizeof(*pIocpOverlapped));
                    pIocpOverlapped->pEIocpSocket = reinterpret_cast<CEIocpSocket*>(n);
                    // PostQueuedCompletionStatus和GetQueuedCompletionStatus只是傳遞pIocpOverlapped這地址的值
                    // 所以對這個地址的內存管理需要程序員自己實現
                    BOOL bResult = PostQueuedCompletionStatus(ms_hIoComplete, n, 0, pIocpOverlapped);
                    if (FALSE == bResult)
                    {
                            std::cout << __FUNCTION__ << std::endl;
                            std::cout << "error: " << ::GetLastError() << std::endl;
                    }

                }


                return E_OK;
            }


            void CEIocpSocket::Thread_EIocpSocket(Thread_EIocpSocket_StartParameter pStartParameter)
            {
                std::cout << __FUNCTION__ << std::endl;

                DWORD nLenTransferred = 0;
                CEIocpSocket* pEIocpSocket = NULL;
                EIOCP_OVERLAPPED* pIocpOverlapped = NULL;

                ULONG_PTR ulKey = NULL;
                OVERLAPPED* pOverlapped;

                while(true)
                {
                    BOOL bResult =
                        GetQueuedCompletionStatus(pStartParameter.hIoComplete,
                        &nLenTransferred, 
                        &ulKey,
                        &pOverlapped,
                        INFINITE);
                    pEIocpSocket = reinterpret_cast<CEIocpSocket*>(ulKey);
                    pIocpOverlapped = static_cast<EIOCP_OVERLAPPED*>(pOverlapped);
                    if(FALSE == bResult)
                    {
                        DWORD ewLastError = ::GetLastError();
                        if(WAIT_TIMEOUT == ewLastError)
                        {
                            continue;
                        }
                        else
                        {
                            std::cout << __FUNCTION__ << std::endl;
                            std::cout << "error: " << ewLastError << std::endl;
                            return;
                        }
                    }
                    else
                    {
                        std::cout << nLenTransferred << std::endl;
                        std::cout << reinterpret_cast<int>(pIocpOverlapped->pEIocpSocket) << std::endl;
                        delete pIocpOverlapped;
                    }
                }
            }

             

             

            posted @ 2013-03-31 23:53 Enic 閱讀(328) | 評論 (0)編輯 收藏

            先看下boost給的例子,我覺得有問題:

            #include
            <boost/atomic.hpp> class spinlock { private: typedef enum {Locked, Unlocked} LockState; boost::atomic<LockState> state_; public: spinlock() : state_(Unlocked) {} void lock() {
            // 可能這里的boost::memory_order_acquire有原子操作的效果吧,偶不是很理解,不過我覺得這里應該用cae操作才對 while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) { /* busy-wait */ } } void unlock() {
            // 這里都直接寫不做檢查了,更加難以理解 state_.store(Unlocked, boost::memory_order_release); } };

            有可能是我不理解后面的內存訪問參數的意義,給下我自己的實現:
            class CESpinLock : boost::noncopyable
            {
            private:
                typedef 
            enum {emUnlocked = 0, emLocked} EM_LockState;

            public:
                CESpinLock() : m_atomicState(emLocked)
                {
                }

            public:
                
            void lock()
                {
                    EM_LockState state 
            = emUnlocked;
                    
            while(false == m_atomicState.compare_exchange_strong(state, emLocked))
                    {
                        state 
            = emUnlocked;
                    }
                }

                
            void unlock()
                {
                    EM_LockState state 
            = emLocked;
                    
            while(false == m_atomicState.compare_exchange_strong(state, emUnlocked))
                    {
                        state 
            = emLocked;
                    }
                }

            private:
                boost::atomic
            <EM_LockState> m_atomicState;
            };


            可以適當的在false里邊加一點sleep操作感覺。

            還有一點就是不太激烈這里的cae操作分兩種 strong和weak

            bool compare_exchange_weak(T & expected, T desired, memory_order success_order, memory_order failure_order)

            Compare current value with expected, change it to desired if matches. Returns true if an exchange has been performed, and always writes the previous value back in expected. May fail spuriously, so must generally be retried in a loop.

            bool compare_exchange_strong(T & expected, T desired, memory_order order)

            Compare current value with expected, change it to desired if matches. Returns true if an exchange has been performed, and always writes the previous value back in expected

            實在不理解 May fail spuriously, so must generally be retried in a loop.的意義,不過看了代碼,在win32的實現上,weak是調用了stong實現的。



             VCZH.粉絲數組[0]<errorcpp@qq.com>  21:49:07
            atomic的 compare_exchange_weak
            compare_exchange_weak
            有啥區別

            求解釋
            vczh.Iskandar<vczh@163.com>  21:49:27
            不是一樣嗎
            御虛舟北(314969051)  21:49:40
            改代碼中, ing
            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:49:49
            Windows上的實現是一樣的
            May fail spuriously, so must generally be retried in a loop. 
            這一句怎么理解呢
            vczh.Iskandar<vczh@163.com>  21:50:07
            compare_exchange_weak
            compare_exchange_weak
            質量最大vczh粉(402740419)  21:50:14
            compare_exchange_weak
            compare_exchange_weak

            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:50:16
            strong

            compare_exchange_strong
            還有一個問題
            class spinlock {
            private:
              typedef enum {Locked, Unlocked} LockState;
              boost::atomic<LockState> state_;

            public:
              spinlock() : state_(Unlocked) {}

              void lock()
              {
                while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) {
                  /* busy-wait */
                }
              }
              void unlock()
              {
                state_.store(Unlocked, boost::memory_order_release);
              }
            };

            boost例子給的 spinloc
            怎么是這樣實現的
            都沒有用cae操作
            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:51:20
            unlock都直接用store了
            vczh.Iskandar<vczh@163.com>  21:51:50
            不用compare
            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:51:59
             為啥
            無法理解
            vczh.Iskandar<vczh@163.com>  21:52:34
            想要解釋好麻煩
            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:52:40
            還有在Windows上
            boost::memory_order_acquire
            這個參數也沒用
            貌似
            求V神解釋
            還有strong和weak的區別
            質量最大vczh粉(402740419)  21:54:46
            spinlock本來就不用compare啊
            直接swap就行了
            while (state_.swap(1) == 1);
            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:56:24
            你看假設現在是lock狀態
            boost的實現是無條件吧lock換成unlock
            如果是繼續lock 他還是lock
            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:58:08
            只要要避免 重入吧
            lock之前檢查一下
            御虛舟北(314969051)  22:00:03
            小康你的書收到沒有
            質量最大vczh粉(402740419)  22:03:17
            VCZH.粉絲數組[0]<errorcpp@qq.com>  21:58:08
            只要要避免 重入吧
            lock之前檢查一下

            你用錯了他不管你
            就是這個意思
            同一個線程lock兩次也會死鎖
            VCZH.粉絲數組[0]<errorcpp@qq.com>  22:05:05
            原來是這樣

            但是他lock的時候不檢查,也會導致兩個線程同時lock吧?
            while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) {
                  /* busy-wait */
                }

            質量最大vczh粉(402740419)  22:05:18
            不會啊
            假設A進程先來了,lock成功了
            VCZH.粉絲數組[0]<errorcpp@qq.com>  22:05:33
            怎能理解,我理解和直接賦值是一樣
            我再去看
            質量最大vczh粉(402740419)  22:05:40
            這不是復制
            是exchange
            swap
            另一個線程exchange就會收到Locked
            那么另一個線程就會while循環,直到原來線程給設置了Unlocked
            VCZH.粉絲數組[0]<errorcpp@qq.com>  22:06:47
            Exchange current value with new_value, returning current value 

            exchange是把新值寫入舊值返回么?  不是這樣么?
            我有點理解了
            質量最大vczh粉(402740419)  22:07:46
            對啊,新值寫入,舊值返回,原子的
            VCZH.粉絲數組[0]<errorcpp@qq.com>  22:07:59
            就是說寫入也是寫入的lock, 不影響之前的lock
            當前線程拿到舊值檢查是不是lock狀態,如果是就繼續嘗試直到不是
            質量最大vczh粉(402740419)  22:08:00
            所以只會有一個線程返回Unlocked,另一個線程會收到之前線程設置的Locked
            VCZH.粉絲數組[0]<errorcpp@qq.com>  22:08:11
             受教了
            質量最大vczh粉(402740419)  22:08:13

            VCZH.粉絲數組[0]<errorcpp@qq.com>  22:08:20
            我貼到博客上去 

            posted @ 2013-03-31 21:49 Enic 閱讀(3787) | 評論 (1)編輯 收藏

            void TestMainEntry()
            {
                boost::asio::io_service ioService;
                boost::asio::ip::tcp::socket tcpSocket(ioService);
                boost::asio::ip::tcp::socket tcpSocket1(ioService);
               // tcpSocket = tcpSocket1;
            }
            void TestIfFstreamCanCopy()
            {
                std::fstream fs0;
                std::fstream fs1;
                // cause compile error
                //fs0 = fs1;
            }



            猶豫的時候去看了下asio,發現asio的是不能copy的,然后去看了下類似fstream,發現也是不能拷貝的。
            分析了下原因,像socket、文件句柄、或者是stream類似的東西,本來就不應該出現多個拷貝,如果有多個拷貝就有多個讀寫入口,這樣會放縱程序員擴散這些入口。
            在配上多線程和多模塊多入口寫入,就會把系統復雜化。
            posted @ 2013-03-30 16:03 Enic 閱讀(159) | 評論 (0)編輯 收藏

            // IOCP_Learn.cpp : Defines the entry point for the console application.
            //
            #include "stdafx.h"
            #include <iostream>
            #include <WinSock2.h>
            // 根據某結構體中一個成員的地址,計算出外層結構體的地址
            //CONTAINING_RECORD
            class CTest_CONTAINING_RECORD
            {
            public:
                void Test()
                {
                    CTest_CONTAINING_RECORD* pTest = CONTAINING_RECORD(&m_i, CTest_CONTAINING_RECORD, m_i);
                    std::cout << reinterpret_cast<unsigned int>(this) << std::endl;
                    std::cout << reinterpret_cast<unsigned int>(pTest) << std::endl;
                }
            private:
                int m_i;
            };
            //OVERLAPPED
            namespace iocp
            {
            enum EM_IOCP_OP_TYPE
            {
                emIOCP_POST_SEND = 0, 
                emIOCP_POST_ASYNC_RECV,
                emIOCP_POST_ACCEPT,
                emIOCP_DISSCONNECT
            };
            };//~ end of namespace iocp
            // 直接繼承OVERLAPPED,根據C++對象的內存布局可以確定stIOCP_OVERLAPPED和static_cast<OVERLAPPED>(obj_stIOCP_OVERLAPPED)
            // 是一樣的
            struct stIOCP_OVERLAPPED : public OVERLAPPED
            {
                WSABUF wsabuf;
                EM_IOCP_OP_TYPE optype;
            };

            // 還有一個是關聯的key,沒有提到,以及關聯socket句柄和完成提示
            int _tmain(int argc, _TCHAR* argv[])
            {
                CTest_CONTAINING_RECORD test;
                test.Test();
            return 0;
            }
            posted @ 2013-03-28 23:25 Enic 閱讀(290) | 評論 (0)編輯 收藏

            // 只讀遍歷
            std::hash_map<std::string, std::string> testMap;
            for(auto iter : testMap)
            {
            }
            posted @ 2013-03-20 11:28 Enic 閱讀(429) | 評論 (2)編輯 收藏

            class CBase
            {
            public:
            int i[255];
            };
            class CSubA : public CBase
            {
            public:
            int m_iA[255];
            };
            class CSubC : public CBase
            {
            public:
            int m_iC[255];
            };
            class CSubSub : public CSubA, public CSubC
            {
            public:
            int m_iss[255];
            };
            int _tmain(int argc, _TCHAR* argv[])
            {
            //CFieldManager fieldManager;
            //fieldManager.RegisterType("", "", 1, 1);
            //unsigned short i = 0x123;
            //unsigned short usMax = USHRT_MAX;
            //std::cout << std::setfill ('0') << std::setw(4) <<  std::hex << i << std::endl;
            //std::cout << std::dec << 9 << std::endl;
            //std::hash_map<std::string, std::string> testMap;
            //std::string strTem;
            //testMap["123"] = "123";
            //testMap.find(strTem);
            //double dResult = 2.f / 3.f;
            //TestCounting();
            //TestList();
            //while (true)
            {
            CSubA * pSubA = new CSubA;
            CBase * pBaseA = pSubA;
            CSubC * pSubC = new CSubC;
            CBase * pBaseC = pSubC;
            std::cout << reinterpret_cast<unsigned int>(pBaseA) << std::endl;
            std::cout << reinterpret_cast<unsigned int>(pSubA) << std::endl;
            std::cout << reinterpret_cast<unsigned int>(pBaseA) << std::endl;
            std::cout << reinterpret_cast<unsigned int>(pSubC) << std::endl;
            delete pBaseA;
            delete pBaseC;
            CSubSub * pSubSub = new CSubSub;
            CSubA * pSubATest =  pSubSub;
            delete pSubATest;
            pSubSub = new CSubSub;
            CSubC* pSubCTest = pSubSub;
            delete pSubCTest;
            int i = 0;
            }
            return 0;
            }
            posted @ 2013-03-19 17:58 Enic 閱讀(727) | 評論 (2)編輯 收藏

            僅列出標題
            共22頁: First 13 14 15 16 17 18 19 20 21 Last 
            亚洲伊人久久大香线蕉综合图片| 久久91精品国产91久久小草| 91久久福利国产成人精品| 久久精品人人槡人妻人人玩AV| 久久无码高潮喷水| 久久青青草视频| 老男人久久青草av高清| 综合人妻久久一区二区精品 | 99久久国产综合精品女同图片| 久久精品国产清自在天天线| 久久国产精品免费| 人人狠狠综合88综合久久| 久久午夜免费视频| 久久偷看各类wc女厕嘘嘘| 久久99热国产这有精品| 国产精品美女久久久网AV| 久久久久99精品成人片| 无码人妻久久一区二区三区蜜桃| 无码人妻久久一区二区三区| 久久久久久久久久久久中文字幕 | 久久国产免费观看精品| 日韩亚洲欧美久久久www综合网 | 伊人久久大香线蕉亚洲五月天| 色欲久久久天天天综合网精品| 久久婷婷五月综合97色| 国产成人精品久久一区二区三区av | 久久99精品久久久久久hb无码 | 久久夜色精品国产亚洲av| 亚洲婷婷国产精品电影人久久| 亚洲人成精品久久久久| 久久免费国产精品一区二区| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区| 女人高潮久久久叫人喷水| 久久国产精品-国产精品| 欧美久久久久久精选9999| 久久亚洲春色中文字幕久久久| 久久久久这里只有精品| 72种姿势欧美久久久久大黄蕉| 久久久久国色AV免费观看| 久久A级毛片免费观看| 91麻豆国产精品91久久久|