Error

C++博客 首页 新随笔 联系 聚合 管理
  217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks

#

endpoint:描述socket编程体系下的一个端点。一个IP+PORT ?

port还是一样的unsigned short

提供一个data()方法,来返回原生的地址结构体。这是一个好的思路,这样系统就不会封闭了。

 

address: 抽象的一个IP地址,可以是ipv4、ipv6。对外接口一致。具体实现上,是聚合了4和6两个实体。所以提供is_v4 is_v6这样两个函数来确认类型。
  address只提供string到address的转换和构造。具体到address_v6 address_v4以后有提供long到address_v4的转换同时也提供了一系列的帮助函数:
    /// Determine whether the address is a loopback address.
  BOOST_ASIO_DECL bool is_loopback() const;

  /// Determine whether the address is unspecified.
  BOOST_ASIO_DECL bool is_unspecified() const;

  /// Determine whether the address is a class A address.
  BOOST_ASIO_DECL bool is_class_a() const;

  /// Determine whether the address is a class B address.
  BOOST_ASIO_DECL bool is_class_b() const;

  /// Determine whether the address is a class C address.
  BOOST_ASIO_DECL bool is_class_c() const;

  /// Determine whether the address is a multicast address.
  BOOST_ASIO_DECL bool is_multicast() const;
  /// Obtain an address object that represents the loopback address.
  static address_v4 loopback()
  /// Obtain an address object that represents the broadcast address.
  static address_v4 broadcast()

posted @ 2012-11-06 10:46 Enic 阅读(500) | 评论 (0)编辑 收藏

C 宏

1,防止一个头文件被重复包含
#ifndef BODYDEF_H
#define BODYDEF_H
//头文件内容
#endif
2,得到指定地址上的一个字节或字
#define MEM_B( x ) ( *( (byte *) (x) ) )
#define MEM_W( x ) ( *( (word *) (x) ) )
3,得到一个field在结构体(struct)中的偏移量
#define FPOS( type, field ) ( (dword) &(( type *) 0)-> field )
4,得到一个结构体中field所占用的字节数
#define FSIZ( type, field ) sizeof( ((type *) 0)->field )
5,得到一个变量的地址(word宽度)
#define B_PTR( var ) ( (byte *) (void *) &(var) )
#define W_PTR( var ) ( (word *) (void *) &(var) )
6,将一个字母转换为大写
#define UPCASE( c ) ( ((c) >= ''a'' && (c) <= ''z'') ? ((c) - 0x20) : (c) )
7,判断字符是不是10进值的数字
#define DECCHK( c ) ((c) >= ''0'' && (c) <= ''9'')
8,判断字符是不是16进值的数字
#define HEXCHK( c ) ( ((c) >= ''0'' && (c) <= ''9'') ||((c) >= ''A'' && (c) <= ''F'') ||((c) >= ''a'' && (c) <= ''f'') )
9,防止溢出的一个方法
#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
10,返回数组元素的个数
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
11,使用一些宏跟踪调试
ANSI标准说明了五个预定义的宏名。它们是:
_LINE_ (两个下划线),对应%d
_FILE_     对应%s
_DATE_   对应%s
_TIME_    对应%s
_STDC_


宏中"#"和"##"的用法
我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.
#define STR(s)     #s
#define CONS(a,b) int(a##e##b)
Printf(STR(vck));           // 输出字符串"vck"
printf("%d\n", CONS(2,3)); // 2e3 输出:2000

当宏参数是另一个宏的时候
需要注意的是凡宏定义里有用"#"或"##"的地方宏参数是不会再展开.
#define A          (2)
#define STR(s)     #s
#define CONS(a,b) int(a##e##b)
printf("%s\n", CONS(A, A));               // compile error
这一行则是:
printf("%s\n", int(AeA));
INT_MAX和A都不会再被展开, 然而解决这个问题的方法很简单. 加多一层中间转换宏.
加这层宏的用意是把所有宏的参数在这层里全部展开, 那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数
#define STR(s)      _STR(s)          // 转换宏
#define CONS(a,b)   _CONS(a,b)       // 转换宏
printf("int max: %s\n", STR(INT_MAX));          // INT_MAX,int型的最大值,为一个变量 #i nclude<climits>
输出为: int max: 0x7fffffff
STR(INT_MAX) --> _STR(0x7fffffff) 然后再转换成字符串;

printf("%d\n", CONS(A, A));
输出为:200
CONS(A, A) --> _CONS((2), (2)) --> int((2)e(2))

"#"和"##"的一些应用特例
1、合并匿名变量名
#define ___ANONYMOUS1(type, var, line) type var##line
#define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)
#define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)
例:ANONYMOUS(static int); 即: static int _anonymous70; 70表示该行行号;
第一层:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
第二层:                        --> ___ANONYMOUS1(static int, _anonymous, 70);
第三层:                        --> static int _anonymous70;
即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开;

注备:这里面的解释 有点牵强。真正的解释是这样的:

   【宏参数的prescan】
   当一个宏参数被放进宏体时,这个宏参数会首先被全部展开(有例外,见下文)。当展开后的宏参数被放进宏体时,
   预处理器对新展开的宏体进行第二次扫描,并继续展开。例如:
   #define PARAM( x ) x
   #define ADDPARAM( x ) INT_##x
   PARAM( ADDPARAM( 1 ) );
   因为ADDPARAM( 1 ) 是作为PARAM的宏参数,所以先将ADDPARAM( 1 )展开为INT_1,然后再将INT_1放进PARAM。
  
   例外情况是,如果PARAM宏里对宏参数使用了#或##,那么宏参数不会被展开:
   #define PARAM( x ) #x
   #define ADDPARAM( x ) INT_##x
   PARAM( ADDPARAM( 1 ) ); 将被展开为"ADDPARAM( 1 )"。

   使用这么一个规则,可以创建一个很有趣的技术:打印出一个宏被展开后的样子,这样可以方便你分析代码:
   #define TO_STRING( x ) TO_STRING1( x )
   #define TO_STRING1( x ) #x
   TO_STRING首先会将x全部展开(如果x也是一个宏的话),然后再传给TO_STRING1转换为字符串,现在你可以这样:
   const char *str = TO_STRING( PARAM( ADDPARAM( 1 ) ) );去一探PARAM展开后的样子。

  预处理器的确是从内到外展开宏的

2、填充结构
#define FILL(a)   {a, #a}

enum IDD{OPEN, CLOSE};
typedef struct MSG{
IDD id;
const char * msg;
}MSG;

MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
相当于:
MSG _msg[] = {{OPEN, "OPEN"},
              {CLOSE, "CLOSE"}};

3、记录文件名
#define _GET_FILE_NAME(f)   #f
#define GET_FILE_NAME(f)    _GET_FILE_NAME(f)
static char FILE_NAME[] = GET_FILE_NAME(__FILE__);

4、得到一个数值类型所对应的字符串缓冲大小
#define _TYPE_BUF_SIZE(type) sizeof #type
#define TYPE_BUF_SIZE(type)   _TYPE_BUF_SIZE(type)
char buf[TYPE_BUF_SIZE(INT_MAX)];
     --> char buf[_TYPE_BUF_SIZE(0x7fffffff)];
     --> char buf[sizeof "0x7fffffff"];
这里相当于:
char buf[11];

posted @ 2012-11-02 17:40 Enic 阅读(437) | 评论 (2)编辑 收藏

前言
第1章并行让程序运行得更快
你可能会想到的一些问题
采用线程化方法的4个步骤
并行算法的背景知识
共享内存编程与分布式内存编程的比较
本书采用的并发编程方法
第2章是否采用并发
并发算法的设计模型
哪些算法不能并行
第3章算法正确性证明与性能衡量
并行算法的验证
示例:临界区问题
性能测试(程序的执行情况如何)
硬件并行性的发展历史

第4章多线程程序设计中的8条简单规则
规则1:找出真正独立的运算
规则2:在尽可能高的层次上实现并发
规则3:尽早考虑通过增加处理器核的数量来获得可伸缩性
规则4:尽可能使用线程安全的库
规则5:使用正确的多线程模型
规则6:永远不要假设程序会按照某种特定的顺序执行
规则7:尽可能使用线程局部存储或者与特定数据相关的锁
规则8:要敢于对代码进行修改以获得更好的并发性
小结

第5章线程化库
隐式线程化
显式线程化
其他主题
特定领域的库

第6章并行求和与前缀求和
并行求和
前缀求和
选择
最后的思考
第7章映射归约
并发映射运算
并发归约运算
映射归约的应用
映射归约作为一般性并发

第8章排序
冒泡排序
奇偶换位排序
希尔排序
快速排序
基数排序

第9章搜索
未排序的数据序列
二分搜索

第10章图算法
深度优先搜索
最短路径问题
最小生成树

第11章线程化工具
调试器
性能工具
其他主题
再接再厉

posted @ 2012-10-23 09:30 Enic 阅读(272) | 评论 (0)编辑 收藏

image

这个体系中的class职责如下:

*ios_base:定义stream classes的所有“与字符类型以及相应的字符特性(traits)无关”的属性,主要包含状态和格式标志等组件和函数。

*basic_ios<>:定义“与字符类型以及相应的字符特性(traits)相关”的stream classes共同属性,其中包括stream所用的缓冲器。

*basic_istream<>  basic_ostream<>:定义出读写对象,如果不关心国际化问题,一般直接使用char实例化的isteram和ostream。

*basic_iostream<>:读写对象。

*basic_streambuf<>:iostream体系的核心,定义出所有“可改写的stream或,可读取的stream”的接口。其他的stream classes都是利用它进行实际的字符读写操作。

 

    iostream程序严格按照职责分离的原则来设计。basic_ios派生类型只处理数据格式化,实际读写操作由basic_ios派生类所维护的stream buffer完成。streambuf提供读写使用的字符缓冲区,形成对外的一种抽象概念。

posted @ 2012-10-22 14:41 Enic 阅读(169) | 评论 (0)编辑 收藏

 

image                                                                                        

#include <iostream>

#include <boost/timer.hpp>

int _tmain(int argc, _TCHAR* argv[])
{
    boost::timer timer;

    const unsigned int TEST_DATA_LEN = 1440*900;
    char* pDataA = new char[TEST_DATA_LEN];
    memset(pDataA, NULL, TEST_DATA_LEN);
    char* pDataB = new char[TEST_DATA_LEN];
    memset(pDataB, NULL, TEST_DATA_LEN);

    double dCopyTime = 0;
    timer.restart();
    for (unsigned int uiLen = 0; uiLen < 1020; uiLen++)
    {
        memcpy(pDataA, pDataB, TEST_DATA_LEN);
    }
    dCopyTime = timer.elapsed();
    std::cout << dCopyTime << std::endl;

    double dMoveTime = 0;
    timer.restart();
    for (unsigned int uiLen = 0; uiLen < 1020; uiLen++)
    {
        memmove(pDataA, pDataA, TEST_DATA_LEN);
    }
    dMoveTime = timer.elapsed();
    std::cout << dMoveTime << std::endl;

    std::cout << "self copy lost:" << (dMoveTime - dCopyTime)*100 << std::endl;

    return 0;
}

posted @ 2012-10-16 11:51 Enic 阅读(243) | 评论 (0)编辑 收藏

// test_demo.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream>

class L1Provider
{
public:
    virtual void L1Service() = 0;
};

class L2Provider
{
public:
    virtual void L2Service() = 0;
    void SetLowerLayer(L1Provider* lv1)
    {
        m_pLv1 = lv1;
    }

protected:
    L1Provider* m_pLv1;
};

class L3Provider
{
public:
    virtual void L3Service() = 0;
    void SetLowerLayer(L2Provider* lv2)
    {
        m_pLv2 = lv2;
    }

protected:
    L2Provider* m_pLv2;
};

class DataLink : public L1Provider
{
public:
    virtual void L1Service()
    {
        std::cout << "lv1 doing its job" << std::endl;
    }
};

class Transport : public L2Provider
{
public:
    virtual void L2Service()
    {
        std::cout << "lv2 start its job" << std::endl;
        m_pLv1->L1Service();
        std::cout << "lv2 end its job" << std::endl;
    }
};

class Session : public L3Provider
{
public:
    virtual void L3Service()
    {
        std::cout << "lv3 start its job" << std::endl;
        m_pLv2->L2Service();
        std::cout << "lv3 end its job" << std::endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    // 实例化个层对象
    DataLink dataLink;
    Transport transport;
    Session session;

    // 安装好层
    transport.SetLowerLayer(&dataLink);
    session.SetLowerLayer(&transport);

    // 工作
    session.L3Service();

    return 0;
}

posted @ 2012-10-12 13:44 Enic 阅读(136) | 评论 (0)编辑 收藏

     摘要: 简化后的CNetClient类图:   本次是分享下整体设计思想,不研究细节网络实现。     CNetClient用户客户端的网络处理。主要功能需求如下: *能接收远端数据 *能把接收到的数据送到上层处理 *能向远端发送数据 **发送和接收都是异步 **CNetClient本身是一个底层服务,对上层是异步的   针对上述需求GodofMon...  阅读全文
posted @ 2012-10-11 17:34 Enic 阅读(395) | 评论 (0)编辑 收藏

 

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

实在是没看出来这样有什么优势,为了记录是否走过某个path?

Query::execute(const SQLString& str)这里看到了递归操作,难道是为了辅助递归?

总感觉这里越搞越复杂,,,

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

/// \brief A template for setting a flag on a variable as long as the
/// object that set it is in scope.  Flag resets when object goes
/// out of scope.  Works on anything that looks like bool.

template <class T = bool>
class AutoFlag
{
public:
    /// \brief Constructor: sets ref to true.
    AutoFlag(T& ref) :
    referent_(ref)
    {
        referent_ = true;
    }

    /// \brief Destructor: sets referent passed to ctor to false.
    ~AutoFlag()
    {
        referent_ = false;
    }

private:
    T& referent_;
};

 

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

ResNSel
Query::execute(const SQLString& str)
{
    if ((def.size() == 1) && !def.processing_) {
        // .  The
        // auto-reset flag is required because we'll end up back in this
        // function once the query string is built, but we need to take
        // the 'else' path to avoid an infinite loop.
        AutoFlag<> af(def.processing_);
        return execute(SQLQueryParms() << str);
    }
    else {
        // Take str to be the entire query string
        return execute(str.c_str(), str.length());
    }
}

ResNSel
Query::execute(const char* str)
{
    return execute(SQLString(str));
}

ResNSel
Query::execute(const char* str, size_t len)
{
    if (lock()) {
        success_ = false;
        if (throw_exceptions()) {
            throw LockFailed();
        }
        else {
            return ResNSel();
        }
    }

    success_ = !mysql_real_query(&conn_->mysql_, str, len);

    unlock();
    if (success_) {
        return ResNSel(conn_);
    }
    else if (throw_exceptions()) {
        throw BadQuery(error());
    }
    else {
        return ResNSel();
    }
}

posted @ 2012-10-08 11:51 Enic 阅读(107) | 评论 (0)编辑 收藏

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

简介:内存DC,又名“双缓冲”,是解决windows窗口自绘中出现“闪屏”的常规手段。

1)、为屏幕 DC 创建兼容的内存 DC
2)、创建位图
3)、把位图选入设备环境
4)、把绘制好的图形“拷贝“到屏幕上

 

看这个代码:

首先看构造,从一个CDC构造。然后看了一下成员函数,好像没几个,估计这是一个可以完全替换的CDC的省心的东东。

然后看析构:析构是一个BitBit,联想自己做内存DC的时候,最后一步也是内存到DC的贴图动作。

公开接口就两个,重载的CDC* 和 ->操作,直接能当作CDC使用。

这几个细节需要注意:

1.m_bMemDC = !pDC->IsPrinting();  // 以前关注不多,这是用于判断这个DC是不是用于print,如果是就不使用“内存DC”,至于为什么还不了解。我理解是没有需要。

2.FillSolidRect(m_rect, pDC->GetBkColor());  // WM_ERASEBKGND,针对这个消息的细节处理。

 

这个类持有了一个“前台”DC,它本身是一个“后台”DC,每次后台克隆前台执行绘画然后把结果贴回去。

这里还有一个细节,就是SelectObject。为了保证不泄漏,最好的办法是,每次工作完成将所有的GDI对象复位。

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

class CMemDC : public CDC
{
public:

    // constructor sets up the memory DC
    CMemDC(CDC* pDC) : CDC()
    {
        ASSERT(pDC != NULL);

        m_pDC = pDC;
        m_pOldBitmap = NULL;
#ifndef _WIN32_WCE_NO_PRINTING
        m_bMemDC = !pDC->IsPrinting();
#else
        m_bMemDC = FALSE;
#endif

        if (m_bMemDC)    // Create a Memory DC
        {
            pDC->GetClipBox(&m_rect);
            CreateCompatibleDC(pDC);
            m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
            m_pOldBitmap = SelectObject(&m_bitmap);
#ifndef _WIN32_WCE
            SetWindowOrg(m_rect.left, m_rect.top);
#endif
            // EFW - Bug fix - Fill background in case the user has overridden
            // WM_ERASEBKGND.  We end up with garbage otherwise.
            // CJM - moved to fix a bug in the fix.
            FillSolidRect(m_rect, pDC->GetBkColor());
        }
        else        // Make a copy of the relevent parts of the current DC for printing
        {
#if !defined(_WIN32_WCE) || ((_WIN32_WCE > 201) && !defined(_WIN32_WCE_NO_PRINTING))
            m_bPrinting = pDC->m_bPrinting;
#endif
            m_hDC       = pDC->m_hDC;
            m_hAttribDC = pDC->m_hAttribDC;
        }

    }

    // Destructor copies the contents of the mem DC to the original DC
    ~CMemDC()
    {
        if (m_bMemDC)
        {
            // Copy the offscreen bitmap onto the screen.
            m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
                          this, m_rect.left, m_rect.top, SRCCOPY);

            //Swap back the original bitmap.
            SelectObject(m_pOldBitmap);
        } else {
            // All we need to do is replace the DC with an illegal value,
            // this keeps us from accidently deleting the handles associated with
            // the CDC that was passed to the constructor.
            m_hDC = m_hAttribDC = NULL;
        }
    }

    // Allow usage as a pointer
    CMemDC* operator->() {return this;}
    // Allow usage as a pointer
    operator CMemDC*() {return this;}

private:
    CBitmap  m_bitmap;      // Offscreen bitmap
    CBitmap* m_pOldBitmap;  // bitmap originally found in CMemDC
    CDC*     m_pDC;         // Saves CDC passed in constructor
    CRect    m_rect;        // Rectangle of drawing area.
    BOOL     m_bMemDC;      // TRUE if CDC really is a Memory DC.
};

posted @ 2012-10-08 10:41 Enic 阅读(210) | 评论 (0)编辑 收藏

#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
#include <fstream>
int main(int argc, char *argv[])
{
   std::wstring str = L"123,我是谁?我爱钓鱼岛!";
   std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
   std::string narrowStr = conv.to_bytes(str);
   {
      std::ofstream ofs ("c:\\test.txt");
      ofs << narrowStr;
   }
   std::wstring wideStr = conv.from_bytes(narrowStr);
   {
      std::locale::global(std::locale("Chinese-simplified"));
      std::wofstream ofs (L"c:\\testW.txt");
      ofs << wideStr;
   }

posted @ 2012-09-12 13:37 Enic 阅读(101) | 评论 (0)编辑 收藏

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