Adaptive Communication Environment (ACE) 是
![](/icons/65134yi.gif)
个高性能、开放源码、面向对象
![](/icons/65134de.gif)
框架和 C
![](/icons/65134jiajia.gif)
类库
![](/icons/65134dou.gif)
它有助于简化网络应用
![](/icons/65134chengxu.gif)
![](/icons/65134de.gif)
开发
![](/icons/65134dou2.gif)
ACE 工具包包括
![](/icons/65134yi.gif)
个操作系统层和
![](/icons/65134yi.gif)
个封装网络 API
![](/icons/65134de.gif)
C
![](/icons/65134jiajia.gif)
外观(facades)集合
![](/icons/65134dou2.gif)
本文讨论如何使用 ACE 线程设计高性能、并发、面向对象
![](/icons/65134de.gif)
网络应用
![](/icons/65134chengxu.gif)
![](/icons/65134dou2.gif)
对 ACE
![](/icons/65134de.gif)
完整介绍说明
![](/icons/65134dou.gif)
包括如何下载和安装这个工具包
![](/icons/65134dou.gif)
请参见 参考资料
用于创建和管理线程
![](/icons/65134de.gif)
ACE 类
在进程中生成和管理多个线程涉及下面
![](/icons/65134de.gif)
类:
ACE_Thread_Manager:这是负责创建、管理和同步线程
![](/icons/65134de.gif)
主要
![](/icons/65134de.gif)
类
![](/icons/65134dou2.gif)
每种操作系统在处理线程方面有细微差异
![](/icons/65134dou.gif)
这个类对应用
![](/icons/65134chengxu.gif)
开发人员隐藏这些差异
ACE_Sched_Params:使用这个类管理各个线程
![](/icons/65134de.gif)
调度优先级
![](/icons/65134dou.gif)
调度优先级是在 ACE 源代码发行版
![](/icons/65134de.gif)
ace/Sched_Params.h 头文件中定义
![](/icons/65134de.gif)
![](/icons/65134dou2.gif)
可以采用区别
![](/icons/65134de.gif)
调度策略
![](/icons/65134dou.gif)
可以是 “先到先服务”
![](/icons/65134de.gif)
循环方式
ACE_TSS:在多线程应用
![](/icons/65134chengxu.gif)
中使用全局变量会导致同步问题
![](/icons/65134dou2.gif)
ACE_TSS 类提供和线程相关
![](/icons/65134de.gif)
存储模式
![](/icons/65134dou.gif)
可以对那些对于
![](/icons/65134chengxu.gif)
是全局
![](/icons/65134de.gif)
![](/icons/65134dou.gif)
但是对于每个线程私有
![](/icons/65134de.gif)
数据提供抽象
![](/icons/65134dou2.gif)
ACE_TSS 类提供 operator
![](/icons/65134kh.gif)
思路方法
![](/icons/65134dou.gif)
这个思路方法提供和线程相关
![](/icons/65134de.gif)
数据
了解线程管理器类
原生操作系统线程 API 是不可移植
![](/icons/65134de.gif)
:存在语法和语义差异
![](/icons/65134dou2.gif)
例如
![](/icons/65134dou.gif)
UNIX® pthread_create
![](/icons/65134kh.gif)
和 Windows® CreateThread
![](/icons/65134kh.gif)
思路方法都创建线程
![](/icons/65134dou.gif)
但是语法不
![](/icons/65134yi.gif)
样
![](/icons/65134dou2.gif)
ACE_Thread_Manager 类提供以下功能:
它可以生成
![](/icons/65134yi.gif)
个或更多线程
![](/icons/65134dou.gif)
每个线程运行自己指定
![](/icons/65134de.gif)
![](/icons/65134hanshu.gif)
![](/icons/65134dou2.gif)
它可以作为
![](/icons/65134yi.gif)
个集合(称为 线程组)管理相关
![](/icons/65134de.gif)
线程
![](/icons/65134dou2.gif)
它管理各个线程
![](/icons/65134de.gif)
调度优先级
![](/icons/65134dou2.gif)
它允许在线程的间进行同步
![](/icons/65134dou2.gif)
它可以修改线程属性
![](/icons/65134dou.gif)
比如堆栈大小
![](/icons/65134dou2.gif)
表 1 介绍 ACE_Thread_Manager 类
![](/icons/65134de.gif)
重要思路方法
表 1. ACE_Thread_Manager 类
![](/icons/65134de.gif)
思路方法
思路方法名 介绍说明
instance ACE_Thread_Manager 类是
![](/icons/65134yi.gif)
个单例子类
![](/icons/65134dou.gif)
使用这个思路方法访问线程管理器
![](/icons/65134de.gif)
惟
![](/icons/65134yi.gif)
例子
spawn 这个思路方法创建
![](/icons/65134yi.gif)
个新线程
![](/icons/65134dou.gif)
它
![](/icons/65134de.gif)
![](/icons/65134yi.gif)
个输入参数是 C/C
![](/icons/65134hanshu.gif)
指针
![](/icons/65134dou.gif)
这个
![](/icons/65134hanshu.gif)
执行应用
![](/icons/65134chengxu.gif)
![](/icons/65134de.gif)
特定工作
exit 这个思路方法终止
![](/icons/65134yi.gif)
个线程
![](/icons/65134dou.gif)
释放这个线程
![](/icons/65134de.gif)
所有资源
spawn_n 这个思路方法创建属于同
![](/icons/65134yi.gif)
个线程组
![](/icons/65134de.gif)
多个线程
close 这个思路方法关闭已经创建
![](/icons/65134de.gif)
所有线程并释放它们
![](/icons/65134de.gif)
资源
suspend 线程管理器暂停指定
![](/icons/65134de.gif)
线程
resume 线程管理器恢复执行前面暂停
![](/icons/65134de.gif)
线程
使用 ACE_Thread_Manager 类
![](/icons/65134de.gif)
变体
可以作为单例子类使用 ACE_Thread_Manager 类
![](/icons/65134dou.gif)
也可以创建这个类
![](/icons/65134de.gif)
多个例子
![](/icons/65134dou2.gif)
对于单
![](/icons/65134yi.gif)
例子
![](/icons/65134dou.gif)
通过
![](/icons/65134diaoyong.gif)
instance 思路方法访问例子
![](/icons/65134dou2.gif)
如果需要管理多个线程组
![](/icons/65134dou.gif)
可以创建区别
![](/icons/65134de.gif)
线程管理器类
![](/icons/65134dou.gif)
每个类控制它自己
![](/icons/65134de.gif)
线程集
清单 1 中
![](/icons/65134de.gif)
举例创建
![](/icons/65134yi.gif)
个线程
![](/icons/65134dou2.gif)
清单 1. 使用 ACE_Thread_Manager 类创建
![](/icons/65134yi.gif)
个线程
#
"ace/Thread_Manager.h"
#
<iostream>
void thread_start(void* arg)
{
std::cout << "Running thread..\n";
}
ACE_TMAIN (
argc, ACE_TCHAR* argv
)
{
ACE_Thread_Manager::instance
->spawn((ACE_THR_FUNC)thread_start);
0;
}
清单 2 给出 spawn
![](/icons/65134kh.gif)
思路方法
![](/icons/65134de.gif)
原型(取自 ace/Thread_Manager.h)
清单 2. ACE_Thread_Manager::spawn 思路方法
![](/icons/65134de.gif)
原型
spawn (ACE_THR_FUNC func,
void *arg = 0,
long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED,
ACE_thread_t *t_id = 0,
ACE_hthread_t *t_handle = 0,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
grp_id = -1,
void *stack = 0,
size_t stack_size = ACE_DEFAULT_THREAD_STACKSIZE,
const char** thr_name = 0);
对于初学者来说
![](/icons/65134dou.gif)
创建线程需要
![](/icons/65134de.gif)
参数数量似乎太多了
![](/icons/65134dou.gif)
所以我们详细讨论
![](/icons/65134yi.gif)
下各个参数和它们
![](/icons/65134de.gif)
作用:
ACE_THR_FUNC func:这是在生成线程时
![](/icons/65134diaoyong.gif)
![](/icons/65134de.gif)
![](/icons/65134hanshu.gif)
void* arg:这是在生成线程时
![](/icons/65134diaoyong.gif)
![](/icons/65134de.gif)
![](/icons/65134hanshu.gif)
![](/icons/65134de.gif)
参数
![](/icons/65134dou2.gif)
void* 意味着用户可以传递应用
![](/icons/65134chengxu.gif)
特有
![](/icons/65134de.gif)
任何数据类型
![](/icons/65134dou.gif)
甚至可以使用某种结构把多个参
![](/icons/65134shuzu.gif)
合成单
![](/icons/65134yi.gif)
数据
long flags:使用 flags 变量设置生成
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
几个属性
![](/icons/65134dou2.gif)
各个属性都由单
![](/icons/65134yi.gif)
位表示
![](/icons/65134dou.gif)
按照 “或” 关系组合在
![](/icons/65134yi.gif)
起
![](/icons/65134dou2.gif)
表 2 介绍说明
![](/icons/65134yi.gif)
些属性
ACE_thread_t *t_id:使用这个
![](/icons/65134hanshu.gif)
访问创建
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
ID
![](/icons/65134dou2.gif)
每个线程具有惟
![](/icons/65134yi.gif)
![](/icons/65134de.gif)
ID
long priority:这是生成
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
优先级
![](/icons/65134int.gif)
grp_id:如果提供这个参数
![](/icons/65134dou.gif)
那么它表示生成
![](/icons/65134de.gif)
线程是否属于现有
![](/icons/65134de.gif)
某
![](/icons/65134yi.gif)
线程组
![](/icons/65134dou2.gif)
如果传递 -1
![](/icons/65134dou.gif)
那么创建新
![](/icons/65134de.gif)
线程组并在这个组中添加生成
![](/icons/65134de.gif)
线程
void* stack:这是预先分配
![](/icons/65134de.gif)
堆栈区域
![](/icons/65134de.gif)
指针
![](/icons/65134dou2.gif)
如果提供 0
![](/icons/65134dou.gif)
就请求操作系统提供生成
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
堆栈区域
size_t stack_size:这个参数指定线程堆栈
![](/icons/65134de.gif)
大小(字节数)
![](/icons/65134dou2.gif)
如果对于前
![](/icons/65134yi.gif)
个参数(堆栈指针)指定了 0
![](/icons/65134dou.gif)
那么请求操作系统提供大小为 stack_size
![](/icons/65134de.gif)
堆栈区域
const char** thr_name:这个参数只和支持线程命名
![](/icons/65134de.gif)
平台(比如 VxWorks)相关
![](/icons/65134dou2.gif)
对于 UNIX 平台
![](/icons/65134dou.gif)
在大多数情况下忽略它
表 2. 线程属性及其介绍说明
线程创建标志 介绍说明
THR_CANCEL_DISABLE 不允许取消这个线程
THR_CANCEL_ENABLE 允许取消这个线程
THR_DETACHED 创建异步线程
![](/icons/65134dou2.gif)
线程
![](/icons/65134de.gif)
退出状态对于其他任何线程不可用
![](/icons/65134dou2.gif)
当线程终止时
![](/icons/65134dou.gif)
操作系统回收线程资源
THR_JOINABLE 允许新线程
![](/icons/65134de.gif)
退出状态对于其他线程可用
![](/icons/65134dou2.gif)
这也是 ACE 创建
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
默认属性
![](/icons/65134dou2.gif)
当这种线程终止时
![](/icons/65134dou.gif)
操作系统不回收线程资源
![](/icons/65134dou.gif)
直到其他线程联结它为止
THR_NEW_LWP 创建显式
![](/icons/65134de.gif)
内核级线程(而不是用户级线程)
THR_SUSPENDED 创建处于暂停状态
![](/icons/65134de.gif)
新线程
清单 3 中
![](/icons/65134de.gif)
举例使用线程管理器类
![](/icons/65134de.gif)
spawn_n 思路方法创建多个线程
清单 3. 使用 ACE_Thread_Manager 类创建多个线程
#
"ace/Thread_Manager.h"
#
<iostream>
void pr
(void* args)
{
id = ACE_Thread_Manager::instance
->thr_self
;
std::cout << "Thread Id: " << id << std::endl;
}
ACE_TMAIN (
argc, ACE_TCHAR* argv
)
{
ACE_Thread_Manager::instance
->spawn_n(
4, (ACE_THR_FUNC) pr
, 0, THR_JOINABLE | THR_NEW_LWP);
ACE_Thread_Manager::instance
->wait
;
0;
}
ACE 中
![](/icons/65134de.gif)
另
![](/icons/65134yi.gif)
种线程创建机制
本节讨论 ACE 提供
![](/icons/65134de.gif)
另
![](/icons/65134yi.gif)
种线程创建/管理机制
![](/icons/65134dou2.gif)
这种思路方法不需要对线程管理器进行显式
![](/icons/65134de.gif)
细粒度
![](/icons/65134de.gif)
控制
![](/icons/65134dou2.gif)
在默认情况下
![](/icons/65134dou.gif)
每个进程在创建时有
![](/icons/65134yi.gif)
个线程
![](/icons/65134dou.gif)
这个线程在
![](/icons/65134hanshu.gif)
开始时启动
![](/icons/65134dou.gif)
在
![](/icons/65134main.gif)
结束时终止
![](/icons/65134dou2.gif)
其他线程都需要显式地创建
![](/icons/65134dou2.gif)
创建线程
![](/icons/65134de.gif)
另
![](/icons/65134yi.gif)
种方式是创建预定义
![](/icons/65134de.gif)
ACE_Task_Base 类
![](/icons/65134de.gif)
子类
![](/icons/65134dou.gif)
然后覆盖 svc
![](/icons/65134kh.gif)
思路方法
![](/icons/65134dou2.gif)
新线程在 svc
![](/icons/65134kh.gif)
思路方法中启动
![](/icons/65134dou.gif)
在 svc
![](/icons/65134kh.gif)
思路方法返回时终止
![](/icons/65134dou2.gif)
在进
![](/icons/65134yi.gif)
步解释的前
![](/icons/65134dou.gif)
请看
![](/icons/65134yi.gif)
下 清单 4 所示
![](/icons/65134de.gif)
源代码
清单 4. 使用 ACE_Task_Base::svc 创建线程
#
“ace/Task.h”
Thread_1 : public ACE_Task_Base {
public:
virtual
svc( ) {
std::cout << “In child’s thread\n”;
0;
}
};
( )
{
Thread_1 th1;
th1.activate(THR_NEW_LWP|THR_JOINABLE);
th1.wait
;
0;
}
在 svc
![](/icons/65134kh.gif)
思路方法中编写和应用
![](/icons/65134chengxu.gif)
相关
![](/icons/65134de.gif)
线程行为
![](/icons/65134dou2.gif)
通过
![](/icons/65134diaoyong.gif)
activate
![](/icons/65134kh.gif)
思路方法(在 ACE_Task_Base 类中声明和定义)执行线程
![](/icons/65134dou2.gif)
在激活线程的后
![](/icons/65134dou.gif)
![](/icons/65134main.gif)
![](/icons/65134hanshu.gif)
等待子线程完成执行
![](/icons/65134dou2.gif)
这就是 wait
![](/icons/65134kh.gif)
思路方法
![](/icons/65134de.gif)
作用:在 Thread_1 执行完的前
![](/icons/65134dou.gif)
主线程被阻塞
![](/icons/65134dou2.gif)
这
![](/icons/65134yi.gif)
等待过程是必需
![](/icons/65134de.gif)
;否则
![](/icons/65134dou.gif)
主线程会调度子线程并执行退出
![](/icons/65134dou2.gif)
在看到主线程退出时
![](/icons/65134dou.gif)
C 运行时会销毁所有子线程;因此
![](/icons/65134dou.gif)
子线程可能根本没有被调度或执行
详细了解 ACE_Task_Base 类
下面详细看看 ACE_Task_Base 中
![](/icons/65134de.gif)
几个思路方法
清单 5 给出 activate
![](/icons/65134kh.gif)
思路方法
![](/icons/65134de.gif)
原型
清单 5. ACE_Task_Base::activate 思路方法
![](/icons/65134de.gif)
原型
virtual
activate (long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED,
n_threads = 1,
force_active = 0,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
grp_id = -1,
ACE_Task_Base *task = 0,
ACE_hthread_t thread_handles[ ] = 0,
void *stack[ ] = 0,
size_t stack_size[ ] = 0,
ACE_thread_t thread_ids[ ] = 0,
const char* thr_name[ ] = 0);
可以使用 activate
![](/icons/65134kh.gif)
思路方法创建
![](/icons/65134yi.gif)
个或多个线程
![](/icons/65134dou.gif)
每个线程
![](/icons/65134diaoyong.gif)
相同
![](/icons/65134de.gif)
svc
![](/icons/65134kh.gif)
思路方法
![](/icons/65134dou.gif)
所有线程采用相同
![](/icons/65134de.gif)
优先级并具有相同
![](/icons/65134de.gif)
组 ID
![](/icons/65134dou2.gif)
下面简要介绍
![](/icons/65134yi.gif)
些输入参数:
long flags:参见 表 2
![](/icons/65134int.gif)
n_threads:n_threads 指定要创建
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
数量
![](/icons/65134int.gif)
force_active:如果这个标志是 True
![](/icons/65134dou.gif)
而且存在这个任务已经生成
![](/icons/65134de.gif)
线程
![](/icons/65134dou.gif)
那么新生成
![](/icons/65134de.gif)
所有线程会共享以前生成
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
组 ID
![](/icons/65134dou.gif)
忽略传递给 activate
![](/icons/65134kh.gif)
思路方法
![](/icons/65134de.gif)
值
long priority:这个参数指定线程或线程集合
![](/icons/65134de.gif)
优先级
![](/icons/65134dou2.gif)
调度优先级值是和操作系统相关
![](/icons/65134de.gif)
![](/icons/65134dou.gif)
坚持使用默认值 ACE_DEFAULT_THREAD_PRIORITY 是最安全
![](/icons/65134de.gif)
ACE_hthread_t thread_handles:如果 thread_handles 不是零
![](/icons/65134dou.gif)
那么在生成 n 个线程的后
![](/icons/65134dou.gif)
会把各个线程句柄赋值给这个
![](/icons/65134shuzu.gif)
void* stack:如果指定这个参数
![](/icons/65134dou.gif)
它指定
![](/icons/65134yi.gif)
个指针
![](/icons/65134shuzu.gif)
![](/icons/65134dou.gif)
这些指针指向各个线程
![](/icons/65134de.gif)
堆栈基
size_t stack_size:如果指定这个参数
![](/icons/65134dou.gif)
它指定
![](/icons/65134yi.gif)
个整数
![](/icons/65134shuzu.gif)
![](/icons/65134dou.gif)
这些整数表示各个线程堆栈
![](/icons/65134de.gif)
大小
ACE_thread_t thread_ids:如果 thread_ids 不是零
![](/icons/65134dou.gif)
那么这个参数是
![](/icons/65134yi.gif)
个
![](/icons/65134shuzu.gif)
![](/icons/65134dou.gif)
其中包含 n 个新生成
![](/icons/65134de.gif)
线程
![](/icons/65134de.gif)
ID
清单 6 给出 ACE_Task_Base 类中另外几个有用
![](/icons/65134de.gif)
例程
清单 6. ACE_Task_Base 中
![](/icons/65134de.gif)
其他例程
// Block the
thread until all threads of this task are completed
virtual
wait (void);
// Suspend a task
virtual
suspend (void);
// Resume a suspended task.
virtual
resume (void);
// Gets the no. of active threads within the task
size_t thread_count (void) const;
// Returns the id of the last thread whose exit caused the thread count
// of this task to 0. A zero
status implies that the result is
// unknown. Maybe no threads are scheduled.
ACE_thread_t last_thread (void) const;
为了创建处于暂停状态
![](/icons/65134de.gif)
线程(而不是通过
![](/icons/65134diaoyong.gif)
suspend
![](/icons/65134kh.gif)
思路方法显式地暂停)
![](/icons/65134dou.gif)
需要向 activate
![](/icons/65134kh.gif)
思路方法传递 THR_SUSPENDED 标志
![](/icons/65134dou2.gif)
可以通过
![](/icons/65134diaoyong.gif)
resume
![](/icons/65134kh.gif)
思路方法恢复执行线程
![](/icons/65134dou.gif)
见 清单 7
清单 7. 暂停线程和恢复执行
Thread_1 th1;
th1.activate(THR_NEW_LWP|THR_JOINABLE|THR_SUSPENDED);
…// code in the
thread
th1.resume
;
…// code continues in
thread
再看看线程标志
有两种线程:内核级线程和用户级线程
![](/icons/65134dou2.gif)
如果不带任何参数
![](/icons/65134diaoyong.gif)
activate
![](/icons/65134kh.gif)
思路方法
![](/icons/65134dou.gif)
那么默认情况下创建内核级线程
![](/icons/65134dou2.gif)
内核级线程和操作系统直接交互
![](/icons/65134dou.gif)
由内核级调度器调度
![](/icons/65134dou2.gif)
和此相反
![](/icons/65134dou.gif)
用户级线程在进程范围内运行
![](/icons/65134dou.gif)
为了完成某些任务
![](/icons/65134dou.gif)
根据需要 “分配” 内核级线程
![](/icons/65134dou2.gif)
THR_NEW_LWP 标志(activate
![](/icons/65134kh.gif)
思路方法
![](/icons/65134de.gif)
默认参数)总是确保新创建
![](/icons/65134de.gif)
线程是内核级线程
线程钩子
ACE 提供
![](/icons/65134yi.gif)
个全局
![](/icons/65134de.gif)
线程启动钩子
![](/icons/65134dou.gif)
这允许用户执行可以应用于所有线程
![](/icons/65134de.gif)
任何操作
![](/icons/65134dou2.gif)
为了创建启动钩子
![](/icons/65134dou.gif)
需要创建预定义类 ACE_Thread_Hook
![](/icons/65134de.gif)
子类并提供 start
![](/icons/65134kh.gif)
思路方法定义
![](/icons/65134dou2.gif)
start
![](/icons/65134kh.gif)
接受两个参数:
![](/icons/65134yi.gif)
个用户定义
![](/icons/65134hanshu.gif)
![](/icons/65134de.gif)
指针和传递给这个用户定义
![](/icons/65134hanshu.gif)
![](/icons/65134de.gif)
void*
![](/icons/65134dou2.gif)
为了注册钩子
![](/icons/65134dou.gif)
需要
![](/icons/65134diaoyong.gif)
静态思路方法 ACE_Thread_Hook::thread_hook
![](/icons/65134dou.gif)
见 清单 8
清单 8. 使用全局线程钩子
#
"ace/Task.h"
#
"ace/Thread_Hook.h"
#
<iostream>
globalHook : public ACE_Thread_Hook {
public:
virtual ACE_THR_FUNC_RETURN start (ACE_THR_FUNC func, void* arg) {
std::cout << "In created thread\n";
(*func)(arg);
}
};
Thread_1 : public ACE_Task_Base {
public:
virtual
svc( ) {
std::cout << "In child's thread\n";
0;
}
};
ACE_TMAIN (
argc, ACE_TCHAR* argv
)
{
globalHook g;
ACE_Thread_Hook::thread_hook(&g);
Thread_1 th1;
th1.activate
;
th1.wait
;
0;
}
注意
![](/icons/65134dou.gif)
自动传递给启动钩子
![](/icons/65134de.gif)
ACE_THR_FUNC 指针是在执行线程
![](/icons/65134de.gif)
activate
![](/icons/65134kh.gif)
思路方法时
![](/icons/65134diaoyong.gif)
![](/icons/65134de.gif)
相同
![](/icons/65134hanshu.gif)
![](/icons/65134dou2.gif)
以上代码
![](/icons/65134de.gif)
输出是:
In created thread
In child’s thread
结束语
本文简要讨论了如何使用 ACE 框架创建和管理线程
![](/icons/65134dou2.gif)
ACE 框架还有其他
![](/icons/65134yi.gif)
些有用
![](/icons/65134de.gif)
特性
![](/icons/65134dou.gif)
比如互斥、用于同步
![](/icons/65134de.gif)
保护阻塞、共享内存和网络服务