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 阅读(1016) | 评论 (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 阅读(22124) | 评论 (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 阅读(1046) | 评论 (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 阅读(201) | 评论 (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 阅读(316) | 评论 (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 阅读(3764) | 评论 (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 阅读(156) | 评论 (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 阅读(279) | 评论 (0)编辑 收藏

// 只读遍历
std::hash_map<std::string, std::string> testMap;
for(auto iter : testMap)
{
}
posted @ 2013-03-20 11:28 Enic 阅读(422) | 评论 (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 阅读(722) | 评论 (2)编辑 收藏

仅列出标题
共22页: First 13 14 15 16 17 18 19 20 21 Last