ACE,TAO 支持IPhone OS 3.12了

2010年2月2日 没有评论

ACE+TAO+CIAO x.7.6 available for download.

Added support for iPhone OS 3.1.2. The following
environment variable are needed:

IPHONE_TARGET, should be set to either SIMULATOR or
HARDWARE. Set to HARDWARE if you want to deploy
on the iPhone/iPod Touch device.

IPHONE_VERSION, should be set to 3.1.2. One can set
the version to any future or past versions, but
only 3.1.2 has been tried.

分类: TAO 标签:

小技巧:用CxImage将从摄像头获取的图像原始数据转成JPG,然后通过DDS发送出去

2009年11月22日 没有评论

觉得没什么比代码更清楚了。直接上代码.

int VideoPublisher_T::publishVideo(long lw,long lh,ACE_UINT8 * dibData, long size)
{
    ACE_UINT8* jpgImageData = 0;
    long jpgImageDataSize = 0;
    CxImage image;
    Video::FrameDataWriter_var dw =
        Video::FrameDataWriter::_narrow(this->dataWriter_.in());
    if (CORBA::is_nil(dw.in()))
    {
        ACE_ERROR_RETURN((LM_ERROR,"(%t|%T) narrow frame data writer\n"),-1);
    }
    // bytes alignment
    ACE_UINT32 bytesPerLine = 4 * ((lw * 24 + 31)/32);
    // Convert original RGB data to Image
    image.CreateFromArray(
        (unsigned char *)dibData,
        lw,
        lh,
        24,
        bytesPerLine,
        false);
    image.Encode(jpgImageData,jpgImageDataSize,CXIMAGE_FORMAT_JPG);
    image.SetJpegQuality(24);

    Video::Frame frame;
    frame.frameId = 0;
    frame.timestamp = ::getTimestamp();
    frame.deviceId = OPTIONS::instance()->getDeviceId();
    frame.type = Video::IT_JPG;
    frame.deviceInfo = CORBA::string_dup(this->statMsg_);
    frame.image.length(jpgImageDataSize);
    ACE_OS::memcpy(frame.image.get_buffer(),(const void*)jpgImageData,jpgImageDataSize);
    image.FreeMemory(jpgImageData);

    DDS::ReturnCode_t ret = dw->write(frame, DDS::HANDLE_NIL);
    if (ret != DDS::RETCODE_OK)
    {
        ACE_ERROR ((LM_ERROR,
            ACE_TEXT("(%P|%t)ERROR:  write returned %d.\n"), ret));
    }

    return ret;
}

分类: Misc 标签:

运行corba事件循环的线程比较靠谱的方式示例

2009年11月17日 没有评论

int
My_Service::svc()
{
  {
    bool done = false;

    while (!done) {
      try {
        if (orb_->orb_core()->has_shutdown() == false) {
          orb_->run();
        }

        done = true;

      } catch (const CORBA::SystemException& sysex) {
        sysex._tao_print_exception(
          "ERROR: My_Service::svc");

      } catch (const CORBA::UserException& userex) {
        userex._tao_print_exception(
          "ERROR:My_Service::svc");

      } catch (const CORBA::Exception& ex) {
        ex._tao_print_exception(
          "ERROR:My_Service::svc");
      }

      if (orb_->orb_core()->has_shutdown()) {
        done = true;

      } else {
        orb_->orb_core()->reactor()->reset_reactor_event_loop();
      }
    }
  }

  return 0;
}

分类: TAO 标签:

多线程中使用ACE日志策略示例

2009年10月26日 没有评论

0. 本文介绍

    本文通过代码,演示了如何在多线程中使用ACE日志设施(log facilites)代码。本文分为三部分。

第一部分概述了ACE日志设施代码;

第二部分给出完整的源代份和运行结果;

第三部分对相关代码作了说明,其中包括了运行Reactor事件,运行时动态服务加载等。

 

1. ACE日志策略

ACE_Logging_Strategy 提供了一种可以在运行时动态配置ACE日志的机制,通过这种机制

可以设置日志文件的大小以及日志文件的“回转”备份。

ACE_Logging_Strategy  默认使用单体的Reactor,使用者也可以通过

  ACE_Reactor my_reactor;
ACE_Logging_Strategy *logging_strategy = …… // Get instance.
 
  logging_strategy->reactor (&my_reactor);

修改。

ACE_Logging_Strategy 的主要参数说明

-f 用来控制日志的标志位,如

   OSTREAM, STDERR, LOGGER, VERBOSE,
    SILENT, VERBOSE_LITE

-i 指定检测日志文件大小的时间间隔。 单位为秒,默认为0表示不检查。

   ACE_Logging_Strategy  内部实现了定时器。

-m 指定日志文件的大小,单位为Kbytes (千字节数)

-N 指定可以创建日志文件的最多个数。超过个数就“回转”备份,即替换旧的日志文件。

-p 指定输出日志的严重级别

DEBUG, INFO, WARNING, NOTICE, ERROR, CRITICAL, ALERT,
EMERGENCY

如果想禁止输出日志的严重级别,可以这样使用

~DEBUG, ~INFO, ~WARNING,

     ~NOTICE, ~ERROR, ~CRITICAL, ~ALERT, ~EMERGENCY

 

2. 示例的代码

   本文以教学演示为目的,所以代码全部写在同一个文件中。下面是完整的代码

//begin
//file: test_log.cpp
//

// author: stone jiang (http://www.tao-studio.net/blog)

// date:    2009-10-26

 

#include "ace/Log_Msg.h"
#include "ace/Time_Value.h"
#include "ace/OS.h"
#include "ace/Logging_Strategy.h"
#include "ace/ARGV.h"
#include "ace/Dynamic_Service.h"
#include "ace/Service_Config.h"
#include "ace/Reactor.h"
#include "ace/Task.h"

class Task_Reactor : public ACE_Task_Base
{
public:
    virtual int open (void *args = 0);
    virtual int svc (void);
    int  done();
};

int Task_Reactor::open(void *args /* = 0 */)
{
    ACE_DEBUG ((LM_DEBUG, "(%t) TaskReactor::open()\n"));

    return this->activate ();
}

int Task_Reactor::svc()
{
    ACE_DEBUG ((LM_DEBUG, "(%t) TaskReactor::svc()\n"));
    return  ACE_Reactor::instance()->run_event_loop();
}

int  Task_Reactor::done()
{
    ACE_DEBUG ((LM_DEBUG, "(%t) TaskReactor::done()\n"));

    return ACE_Reactor::instance()->end_event_loop();
}

class Task_Test : public ACE_Task<ACE_MT_SYNCH>
{
public:
    virtual int open (void *args = 0);
    virtual int close (u_long flags = 0);
    virtual int svc (void);

private:
};

int
Task_Test::open (void *)
{
    return this->activate ();
}

int
Task_Test::close (u_long)
{
    return 0;
}

int
Task_Test::svc (void)
{

    ACE_DEBUG ((LM_DEBUG, "(%t) svc: waiting\n"));
    for(int i = 0; i < 10;  i++)
    {
        ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%t|%T) Task_Test:: i = %d.\n"),i));
        ACE_OS::sleep(ACE_Time_Value(1,0));

    }

    ACE_DEBUG ((LM_DEBUG, "(%t) svc: finished waiting\n"));
    return 0;
}

int ACE_TMAIN(int argc, ACE_TCHAR *[])
{
    ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%t|%T) start here.\n")));
    ACE_Logging_Strategy *  log =
        ACE_Dynamic_Service<ACE_Logging_Strategy>::instance("Logger");
    if (log == 0)
    {
        int result =  ACE_Service_Config::process_directive(
            ACE_DYNAMIC_SERVICE_DIRECTIVE("Logger",
             "ACE",             
            "_make_ACE_Logging_Strategy",
            "")
            );
        ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%t|%T) result = %d.\n"),result));
    }
    log =
        ACE_Dynamic_Service<ACE_Logging_Strategy>::instance("Logger");

    if (log)
    {
        ACE_ARGV args;
        args.add (__argv[0]);
        char cmdline[250] ={0};
        sprintf(cmdline,"-s log.txt -f STDERR|OSTREAM -p DEBUG|ERROR");
        args.add (ACE_TEXT (cmdline));    
        log->init(args.argc(),args.argv());
    }
    else
    {
        return -1;
    } 

    Task_Test  testTask;
    testTask.open( 0 );
    Task_Reactor reactorTask;
    reactorTask.open(0);

    for(int i = 0; i < 10;  i++)
    {
        ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%t|%T) i = %d.\n"),i));
        ACE_OS::sleep(ACE_Time_Value(1,0));

    }
    testTask.wait();

    reactorTask.done();
    reactorTask.wait();
    ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%t|%T) end here.\n")));
    return 0;
};

//file: test_log.cpp
// end

 

 

代码运地结果

在可执行文件当前目录下,程序自动创建了日志文件log.txt,内容如下

(4728) TaskReactor::open()
(4728| 15:14:34.156000) i = 0.
(4944) TaskReactor::svc()
(3248) svc: waiting
(3248| 15:14:34.156000) Task_Test:: i = 0.
(4728| 15:14:35.156000) i = 1.
(3248| 15:14:35.156000) Task_Test:: i = 1.
(4728| 15:14:36.156000) i = 2.
(3248| 15:14:36.156000) Task_Test:: i = 2.
(4728| 15:14:37.156000) i = 3.
(3248| 15:14:37.156000) Task_Test:: i = 3.
(4728| 15:14:38.156000) i = 4.
(3248| 15:14:38.156000) Task_Test:: i = 4.
(4728| 15:14:39.156000) i = 5.
(3248| 15:14:39.156000) Task_Test:: i = 5.
(4728| 15:14:40.156000) i = 6.
(3248| 15:14:40.156000) Task_Test:: i = 6.
(4728| 15:14:41.156000) i = 7.
(3248| 15:14:41.156000) Task_Test:: i = 7.
(4728| 15:14:42.156000) i = 8.
(3248| 15:14:42.156000) Task_Test:: i = 8.
(4728| 15:14:43.156000) i = 9.
(3248| 15:14:43.156000) Task_Test:: i = 9.
(3248) svc: finished waiting
(4728) TaskReactor::done()
(4728| 15:14:44.156000) end here.

 

3.与程序相关的ACE其它内容

本程序还用到了多线程编程,演示了ACE_Task_Base, ACE_Task<>,的使用;

其中Task_Reactor演示了如何在独立的线程中运行Reactor事件循环,并在主线程中结束Reactor事件循环。

 

本程序还用到了动态服务加载:

ACE_Service_Config::process_directive()

它可以在运行时显示的加载所需要的服务(svc),使用这种手法可以不必编写*.conf文件。

本程序还用到了在程序中根据ident访问直接访问加载的动态服务

ACE_Dynamic_Service<ACE_Logging_Strategy>::instance("Logger");

 

其他:

在学习ACE的过程中如果有任何问题,欢迎来邮件(jiangtao) 或在本站论坛http://www.tao-studio.net/bbs中提问。

分类: ACE 标签:

优先级反转

2009年9月10日 没有评论

Priority Inversion 优先级反转是嵌入式实时系统里面的一个经典的问题。简单描述一下这个问题:有三个优先级不同的task,A,B,C; A的优先级最高,B次之,C最低。其中A和C有共享的临界区。如果C已进入临界区,那么A在进入进入临界区之前,就会被阻塞。task B有可能打断C而进入运行状态,这样C什么时候从临界区退出,就是一个未知的时间。A只有C从临界区退出后才能被调度,A被阻塞的时间也是未知的。这样,低优先级的B先于高优先级的A被调度,优先级发生了逆转。
这个问题在一般的操作系统里面不是一个严重的问题,最多A被多阻塞了一段时间。但是,在实时系统里面,如果一个任务在规定的时间里面没有被调度运行,系统就相当于失败了,可能引发系统崩溃。
解决这个问题有两种手段:
1:Priority inheritance(优先级继承),如果一个高优先级的task被阻塞,与它共享临界区的低优先级的task在进入临界区后,优先级就会继承高优先级task的优先级,保证它不会被其他优先级次高的任务打断。从临界区退出后,C的优先级恢复正常。
2:A priority ceiling(最高优先级),给临界区分配最高优先级,如果一个task进入临界区,就把临界区的优先级赋给它,已保证它不会被打断。从临界区退出后,task的优先级恢复正常。

实时操作系统的一个特点就是,一个实时任务,会在规定的时间内得到响应,并且在规定的时间内完成任务。所以,一切不可预知的动作都是有害的。

有兴趣可以看看下面两个链接:
http://en.wikipedia.org/wiki/Priority_inversion

 

Priority inversion

From Wikipedia, the free encyclopedia

Jump to: navigation, search

In scheduling, priority inversion is the scenario where a low priority task holds a shared resource that is required by a high priority task. This causes the execution of the high priority task to be blocked until the low priority task has released the resource, effectively "inverting" the relative priorities of the two tasks. If some other medium priority task, one that does not depend on the shared resource, attempts to run in the interim, it will take precedence over both the low priority task and the high priority task.

In some cases, priority inversion can occur without causing immediate harm—the delayed execution of the high priority task goes unnoticed, and eventually the low priority task releases the shared resource. However, there are also many situations in which priority inversion can cause serious problems. If the high priority task is left starved of the resources, it might lead to a system malfunction or the triggering of pre-defined corrective measures, such as a watch dog timer resetting the entire system. The trouble experienced by the Mars lander "Mars Pathfinder"[1][2] is a classic example of problems caused by priority inversion in realtime systems.

Priority inversion can also reduce the perceived performance of the system. Low priority tasks usually have a low priority because it is not important for them to finish promptly (for example, they might be a batch job or another non-interactive activity). Similarly, a high priority task has a high priority because it is more likely to be subject to strict time constraints—it may be providing data to an interactive user, or acting subject to realtime response guarantees. Because priority inversion results in the execution of the low priority task blocking the high priority task, it can lead to reduced system responsiveness, or even the violation of response time guarantees.

A similar problem called deadline interchange can occur within Earliest Deadline First Scheduling (EDF).

Contents

[hide]

[edit] Solutions

The existence of this problem has been known since the 1970s, but there is no fool-proof method to predict the situation. There are however many existing solutions, of which the most common ones are:

Disabling all interrupts to protect critical sections
When disabled interrupts are used to prevent priority inversion, there are only two priorities: preemptible, and interrupts disabled. With no third priority, inversion is impossible. Since there’s only one piece of lock data (the interrupt-enable bit), misordering locking is impossible, and so deadlocks cannot occur. Since the critical regions always run to completion, hangs do not occur. Note that this only works if all interrupts are disabled. If only a particular hardware device’s interrupt is disabled, priority inversion is reintroduced by the hardware’s prioritization of interrupts. A simple variation, "single shared-flag locking" is used on some systems with multiple CPUs. This scheme provides a single flag in shared memory that is used by all CPUs to lock all inter-processor critical sections with a busy-wait. Interprocessor communications are expensive and slow on most multiple CPU systems. Therefore, most such systems are designed to minimize shared resources. As a result, this scheme actually works well on many practical systems. These methods are widely used in simple embedded systems, where they are prized for their reliability, simplicity and low resource use. These schemes also require clever programming to keep the critical sections very brief, under 100 microseconds in practical systems. Many software engineers consider them impractical in general-purpose computers.
Arguably, these methods are similar to priority ceilings.
A priority ceiling
With priority ceilings, the shared mutex process (that runs the operating system code) has a characteristic (high) priority of its own, which is assigned to the task locking the mutex. This works well, provided the other high priority task(s) that try to access the mutex does not have a priority higher than the ceiling priority.
Priority inheritance
Under the policy of priority inheritance, whenever a high priority task has to wait for some resource shared with an executing low priority task, the low priority task is assigned the priority of the highest waiting priority task for the duration of its own use of the shared resource, thus keeping medium priority tasks from pre-empting the (originally) low priority task, and thereby effectively the waiting high priority task as well.

[edit] See also

[edit] Notes

  1. ^ What Really Happened on Mars by Glenn Reeves of the JPL Pathfinder team
  2. ^ Explanation of priority inversion problem experienced by Mars Pathfinder

[edit] References

[edit] External links

Retrieved from "http://en.wikipedia.org/wiki/Priority_inversion"

分类: TAO 标签:

让debug和release输出到不同目录的示例

2009年8月28日 没有评论

// DataServerBase.mpb
project {
    specific {
        Release::install = $(DATASERVER_ROOT)/Output/Release
        Debug::install = $(DATASERVER_ROOT)/Output/Debug
        warning_level = 4
    } 
}

分类: TAO 标签:

ACE代码示例:实现计算机网络授时的小程序

2009年8月26日 没有评论

文/江涛

应用说明

 

本代码实现了RFC 868 客户端。启动程序,向给定的时间服务建立TCP连接,时间服务返回4个字节的整数,这个数定是从1900年1月1日零点到当前时间过去的秒数,当然它是网络字节的顺序的,通过网络字节到主机字节转换后,我们就可以读出这个数字。

本程序暂只支持Windows,因为linux下的修改系统时间和Windows的接口不一致,linux下的同学可以自行修改代码。

 

 

//timeclient.cpp
//platform: win32

#include "ace/Log_Msg.h"
#include "ace/Time_Value.h"
#include "ace/OS.h"
#include "ace/Date_Time.h"
#include "ace/streams.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Connector.h"
#include "ace/SOCK_Stream.h"
#include "ace/Get_Opt.h"
#include <string>
using namespace std;
#ifdef WIN32
#include <windows.h>
#endif
#if 0
//可用的部分服务器地址
#define NUMSRV 15
char *serv_ip[NUMSRV]= {"64.236.96.53"   ,/*nist1.aol-va.truetime.com*/
"128.138.140.44" ,/*utcnist.colorado.edu*/
"207.200.81.113" ,/*nist1.aol-ca.truetime.com*/
"216.200.93.8"   ,/*nist1-dc.glassey.com*/
"63.149.208.50"  ,/*nist1.datum.com*/
"208.184.49.9"   ,/*nist1-ny.glassey.com*/
"207.126.103.204",/*nist1-sj.glassey.com*/
"129.6.15.28"    ,/*time-a.nist.gov*/
"129.6.15.29"    ,/*time-b.nist.gov*/
"132.163.4.101"  ,/*time-a.timefreq.bldrdoc.gov*/
"132.163.4.102"  ,/*time-b.timefreq.bldrdoc.gov*/
"132.163.4.103"  ,/*time-c.timefreq.bldrdoc.gov*/
"192.43.244.18"  ,/*time.nist.gov*/
"131.107.1.10"   ,/*time-nw.nist.gov*/ 
"utcnist.colorado.edu"/*DNS entry =128.138.140.44*/
};
#endif

#ifdef WIN32
void TimetToSystemTime( time_t t, LPSYSTEMTIME pst )
{
    FILETIME ft;
    LONGLONG ll = Int32×32To64(t, 10000000) + 116444736000000000;
    ft.dwLowDateTime = (DWORD) ll;
    ft.dwHighDateTime = (DWORD)(ll >> 32);

    FileTimeToSystemTime( &ft, pst );
}

int setSysteTime(const time_t&  t)
{
    SYSTEMTIME st;
    memset(&st,0,sizeof(st));
    TimetToSystemTime(t,&st);
    if (::SetSystemTime(&st))
    {
        ::SendMessage(HWND_BROADCAST, WM_TIMECHANGE, 0, 0);
        return 0;
    }
    return -1;

}
#endif
int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
    ACE_SOCK_Stream peer;
    ACE_SOCK_Connector conn;
    ACE_UINT32 tempValue = 0;
    ACE_INET_Addr address ;
    //(37,);
    string server = "nist1-la.ustiming.org";
    ACE_Get_Opt get_opts (argc, argv, ACE_LIB_TEXT("s:?"));
    int ich;
    while ((ich = get_opts ()) != EOF) {
        switch (ich) {
          case ’s’: /* u specifies that UDP should be used */
              server  = get_opts.opt_arg();
              break;
          case ‘?’: /* t specifies that zero copy read should be used */
              cout << "usage:  timeclient -s \"nist1-la.ustiming.org\"" << endl;
             return -1;

          default: /* no parameters */
              break;
        }
    }

    address.set(37,server.c_str());

    if (-1 ==conn.connect(peer,address))
    {
        ACE_ERROR_RETURN((LM_ERROR,
            "%p",
            "connect"),-1);
    }
    ssize_t n = peer.recv((char*) &tempValue,4);
    if (n > 0)
    {
        //字节序从网络转为主机

        tempValue = ntohl(tempValue);
        tempValue -= 2208988800l; ///*subtract 1970.0 – 1900.0*/
        time_t t(tempValue);   
        if (setSysteTime(t) == 0)
        {
            cout << " adjtime OK." << endl;
        }
        else
        {
            cout << " adjtime error" << endl;
        }    
    }

    peer.close();

    time_t lt;
    lt =time(NULL);
    char* ss = ctime(&lt);
    cout << "the system time " <<  ss << endl;   
    return 0;
};

分类: TAO 标签:

学习ACE需要的基础知识

2009年8月26日 1 条评论

有网友问及学习ACE需要的知识,这个问题很好,我把我认为需要的基础知列一下。

 

1) C++

      需要了解面向对象的基础。如果下面的概念还不太清楚的话,那C++你还没有过关

      1) 虚函数

      2) 派生

      3) 构造函数,构造函数初始化类的过程(初始成员变量,基类,自己的顺序)

      4) 析构函数

      5) 赋值函数和拷贝构造函数

 

      另外,还需要了解基本的泛型编程.

2) 了解基本的TCP/IP协议及socket基础

 

3) 了解设计模式的基础

    提起常用的模式,马上能有对应的UML图在头脑中浮现。当然,UML的基础也是需要的。

 

4)如果需要更好的理解ACE的实现,需要了解POSA(面向设计模式的软件体系结构)

    对于实学者来说,先学学如何用更现实点。

 

综上:ACE适合有一定基础的同学学习,或者觉得自己不错了,想再上几个台阶的同学学习。

分类: TAO 标签:

什么是ACE?为什么它说是开发游戏服务器的利器?

2009年8月25日 没有评论

文/江涛  2009-8-25

 

ACE的全称是The ADAPTIVE Communication Environment ,中文意思是“自适应通讯环境”,它是开源的面向对象的框架(framework)。ACE提供了一组C++的包装类和一组强大的应用框架,非常方便开发各类网络应用的服务器,当然也非常适合开发游戏服务器。

要更好的理解ACE的定义,先来了解一下什么是框架(framework):

如果用框架是什么是什么来解释可能比较费解也比较难懂,让我们换一个角度来看,这个角度就是人们对“代码复用”的认知的过程。首先有需要和大家有一个共识,代码复用度越高就说明它的价值越大

最原始的代码复用是什么呢?这很简单了,那就是在源代码中拷贝粘贴

这种复用局限性太大了,接下来就有子过程和函数,然后就有了函数库,库函数就是C语言的一大特色。

随着硬件越来越强,人们对软件产品的期望越来越高,而软件开发的工艺却停滞不前,在这种矛盾下产生了软件危机,于是,人们开始思想了。面向对象就是人们思想产物中的佼佼者。于是,软件复用进入了一个新的层次,那就是基于类库的函数。

面向对象曾经被寄于厚望,但是,事情上这个世界上不存在包治百病的灵丹妙药(magic bullet),所以,当开发人员面对一些可复用的组件,想象成自己想建筑工人那样把不同砖头堆成高楼大厦时,发现粘合不同对象之间的胶水代码 (glue code)比组件本身更难写,更易出错。 这可怎么办呢? 框架(framework)!这就需要框架。代码的复用过程还在被推进(后面的我以后再介绍)。

ACE就是框架,她不仅仅是一堆类库,她是比类库更好的代码复用。

代码复用的发展归结如下:

拷贝粘贴–>库函数->类库->框架-> (???)->(???)->

所以,无论您是否编写网络程序,ACE也是很好的学习范例。用白话说,ACE源代码大滋大补哦!

 

我们再看网络服务应用,为什么说ACE是开发游戏服务器的利器?

不管你是否写过网络程序,有一些事实需要达成共识,那就是:

1. 网络环境很复杂。 同一个系统,往往是由不同的网络设备,不同时期(当时最好)的服务构成,有时还要运行不同的操作系统。

2. 不同类型的需要对服务要求的特性不同。 比如,游戏的在线用户管理服务,它要求单台机器提供更多的用户接入数;比如监视和控制服务,它要求系统的响应时间和延迟很小;再比如文件下载更新服务,它要求吞吐量能最大。上面的这些特性彼此之间还互相冲突。所以,这也不存在某一个单一的解决方案能解决所有问题。

3. 网络化的应用软件比单机的复杂。写网络程序面临着两方面的挑战。一种是固有的挑战,那就是无论服务多么小,都会面临着

a) 如何选择恰当的通讯机制和协议并有效的应用它们;

b) 如何设计网络服务来使用计算机资源并能减少以后的维护成本;

c) 如何设计有效的并发机制来让系统达到可预测性、可靠性和高性能;

d)如何部署和配置来让服务的可用性和灵活性得到最大化。

另一种是偶发的挑战,那就是:

e)操作系统原生的API都往往缺少类型安全、不可移植、扩展性差;

f)非向对象使用的是算法分解(algorithmic decomposition)的思想,往往会导致服务很难维护和扩展;

h)有人说我们自己做自己的网络开发包。但这种重复发现和发现,使得开发周期和成本都极大的浪费。

 

也许您会问,你说了这么多,ACE到底提供了哪些功能,有哪些优点呢?问得好,ACE提供了编写网络程序都会遇到的问题的解决办法,让您不必重头做起。这些功能包括了:

1.  网络事件的分离并向事件处理器分派出;

2.  信号处理;

3.  服务的初始化;

4.  进程间的通讯;

5.  共享内存管理;

6. 消息处理

7. 分布式服务的动态(再)配置

8. 服务的并发执行和同步

使用ACE让您让您的网络服务:

1) 让可移植性更好;

2) 更好软件的质量

3)   更高效有可预测性

4)   更容易向更高层的标准的中间件转移

哪里下载ACE呢?

ACE的官方网站是

http://www.cs.wustl.edu/~schmidt/ACE.html

ACE是开源的,她的源代码可以自由下载,当前的版本是 5.7.2,下载地址是

HTTP FTP

下载后还需要自行编译。 如何编译请参考 building and installing

 

有不少网友反应,ACE太大太难学了。

呵呵,是啊,ACE不是小玩意,ACE已经经历了十多年发展,历史比Windows操作系统还悠久。她包含了见多开发网络应用的方方面,支持几乎所有的主流操作系统和编译器,所以不小。ACE的包含了数不数的贡献者的智慧。学习ACE需要一定的基础,需要学习者静心修炼。

 

如果您想跟我学ACE,欢迎和我联系。

分类: TAO 标签:

Direct Show 应用程序某个编译错误的解决办法

2009年8月3日 没有评论

新近编程要vc9 (Visual Studio 2008)用到usb摄像头,在编译direct show基础库的时候,遇到如下的错误提示:

:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(222) : error C2146: syntax error : missing ‘;’ before identifier ‘PVOID64′

C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(222) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int

C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C2146: syntax error : missing ‘;’ before identifier ‘Buffer’

C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int

C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int

 

其中C4430好解决,这只是vc6向vc9移植时的一般问题。比较难办的是c2146.

有一种办法是说调整编译器配置选项中的头文件顺序,如

Before I have (he don’t works)
C:\DXSDK\Include
$(VCInstallDir)include
$(VCInstallDir)atlmfc\include
$(VCInstallDir)PlatformSDK\include
$(FrameworkSDKDir)include
Now i solve the problem with the order of directx SDK
$(VCInstallDir)include
$(VCInstallDir)atlmfc\include
$(VCInstallDir)PlatformSDK\include
$(FrameworkSDKDir)include
C:\DXSDK\Include
good luck

 

但上面的办法在某些项目中解决不了,比如dshow自动的示例。下面给出产生这个问题的原因和解决办法。

原因:

DirectX Include目录下面包含了一个叫BaseTsd.h的过期的头文件,它并没有定义类型 ,我们可以命名用Platform SDK的头文件来代替它。

解决办法:

非常简单,把 DirectX Include中的BaseTsd.h删除即可。这样做的优点是,不用再来回调整头文件的顺序了。

分类: Misc 标签: