搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
你好赵伟
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
大语言模型应用指南:长期记忆_大模型长期记忆
2
Iceberg构建
3
(附源码)springboot疫情防控下基于微信小程序的食堂订餐系统 毕业设计261620_微信小程序点餐毕业论文
4
搜索化学反应过渡态的输入文件是什么样的?
5
git did not egxit cleanly(exit code 128)图形界面解决办法_小乌龟git克隆代码128错误
6
fiddler 手机抓包(含https) 完整流程,2024年最新软件测试程序员面试必备的知识点_fiddle抓包手机
7
flutter 笔记 生成安卓签名(mac环境)_mac 对安卓包签名
8
矩阵分解及其在机器学习中的应用
9
[MAC] 编译安装和测试《魔兽世界》模拟服务端 TrinityCore
10
FATS文件管理系统STM32移植_fats移植
当前位置:
article
> 正文
Apple公司Darwin流式服务器源代码分析(二)_darwin 源码分析
作者:你好赵伟 | 2024-07-27 18:54:23
赞
踩
darwin 源码分析
本博客转载于:
http://www.cublog.cn/u/11445/showart.php?id=225276
3
基础功能类库(
Common Utilities
)
3.1 OS
类
Darwin Streaming Server
支持包括
Windows
,
Linux
以及
Solaris
在内的多种操作系统平台。我们知道,
Windows
和
Unix
(或
Unix-like
)操作系统之间无论从内核还是编程接口上都有着本质的区别,即使是
Linux
和
Solaris
,在编程接口上也大为不同。为此,
DSS
开发了多个用于处理时间、临界区、信号量、事件、互斥量和线程等操作系统相关的类,这些类为上层提供了统一的使用接口,但在内部却需要针对不同的操作系统采用不同的方法实现。表
2
罗列出了
DSS
中的主要
OS
类和数据结构。
表
2 DSS
中的主要
OS
类和数据结构
类(数据结构)名
主要功能
OS
平台相关的功能类,如内存分配、时间等
OSCond
状态变量的基本功能和操作
OSMutex
互斥量的基本功能和操作
OSThread
线程类
OSFileSource
简单文件类
OSQueue
队列类
OSHashTable
哈希表类
OSHeap
堆类
OSRef
参考引用类
3.1.1 OSMutex/OSCond Class
在有多个线程并发运行的环境中,能同步不同线程的活动是很重要的,
DSS
开发了
OSMutex
和
OSCond
两个类用以封装不同操作系统对线程同步支持的差异。
我们首先分析
OSMutex
类,这个类定义了广义互斥量的基本操作,类定义如下:
class OSMutex
{
1 public:
2 OSMutex()
;
//
构造函数
3 ~OSMutex()
;
//
析构函数
4 inline void Lock()
;
//
加锁
5 inline void Unlock()
;
//
解锁
6 inline Bool16 TryLock()
;
//
异步锁,无论是否成功立即返回
7 private:
8 #ifdef __Win32__
9 CRITICAL_SECTION fMutex
;
//
临界区
10 DWORD fHolder
;
//
拥有临界区的线程
id
11 UInt32 fHolderCount
;
//
进入临界区线程数
//
其他略
…
}
在
Windows
平台上,
OSMutex
类是通过临界区(
CRITICAL_SECTION
)来实现的,第
10
行定义了临界区变量
fMutex
。类实例化时构造函数调用
InitializeCriticalSection(&fMutex)
初始化临界区变量,对应的在析构函数中调用
DeleteCriticalSection(&fMutex)
清除。
Lock()
函数用于对互斥量加锁,它调用私有方法
RecursiveLock
实现:
void OSMutex::RecursiveLock()
{
//
当前线程已经拥有互斥量,只需增加引用计数
1 if (OSThread::GetCurrentThreadID() == fHolder)
2 {
3 fHolderCount++
;
//
增加引用计数
4 return
;
5 }
6 #ifdef __Win32__
7 ::EnterCriticalSection(&fMutex)
;
//
申请进入临界区
8 #else
9 (void)pthread_mutex_lock(&fMutex)
;
10 #endif
11 Assert(fHolder == 0)
;
12 fHolder = OSThread::GetCurrentThreadID()
;
//
更新临界区拥有者标志
13 fHolderCount++
;
14 Assert(fHolderCount == 1)
;
}
第
1
行检测如果当前线程已经拥有互斥量,就只需将内部计数
fHolderCount
加
1
,以便纪录正在使用互斥量的方法数。如果当前线程还没有得到互斥量,第
7
行调用
EnterCriticalSection()
函数申请进入临界区;如果当前已经有其他线程进入临界区,该函数就会阻塞,使得当前线程进入睡眠状态,直到占用临界区的线程调用
LeaveCriticalSection(&fMutex)
离开临界区后才可能被唤醒。一旦线程进入临界区后,它将首先更新临界区持有者标志(第
12
行),同时将临界区引用计数加
1
。
注意到另外一个函数
TryLock()
,该函数也是用于为互斥量加锁,但与
Lock()
不同的是,
TryLock()
函数为用户提供了异步调用互斥量的功能,这是因为它调用
::TryEnterCriticalSection(&fMutex)
函数申请进入缓冲区:如果临界区没有被任何线程拥有,该函数将临界区的访问区给予调用的线程,并返回
TRUE
,否则它将立刻返回
FALSE
。
TryEnterCriticalSection()
和
EnterCriticalSection()
函数的本质区别在于前者从不挂起线程。
接着分析
OSCond
类,该类定义了状态变量(
Condition Variable
)的基本操作,类定义如下:
class OSCond
{
1 public:
2 OSCond()
;
//
构造函数
3 ~OSCond()
;
//
析构函数
4 inline void Signal()
;
//
传信函数
5 inline void Wait(OSMutex* inMutex, SInt32 inTimeoutInMilSecs = 0)
;
//
等待传信函数
6 inline void Broadcast()
;
//
广播传信函数
7 private:
8 #ifdef __Win32__
9 HANDLE fCondition
;
//
事件句柄
10 UInt32 fWaitCount
;
//
等待传信用户数
//
其他略
…
}
虽然同是用于线程同步,但
OSCond
类与
OSMutex
大不相同,后者用来控制对关键数据的访问,而前者则通过发信号表示某一操作已经完成。在
Windows
平台中,
OSCond
是通过事件(
event
)来实现的;构造函数调用
CreateEvent()
函数初始化事件句柄
fCondition
,而析构函数则调用
CloseHandle()
关闭句柄。
OSCond
的使用流程是这样的:线程调用
Wait(OSMutex* inMutex, SInt32 inTimeoutInMilSecs = 0)
函数等待某个事件的发生,其中
inTimeoutInMilSecs
是最长等待时间,
0
代表无限长。
Wait()
函数内部调用了
WaitForSingleObject (fCondition, theTimeout)
函数,该函数告诉系统线程在等待由事件句柄
fCondition
标识的内核对象变为有信号,参数
theTimeout
告诉系统线程最长愿意等待多少毫秒。如果指定的内核对象在规定时间内没有变为有信号,系统就会唤醒该线程,让它继续执行。而函数
Signal()
正是用来使事件句柄
fCondition
有信号的。
Signal()
函数内部实现很简单,只是简单调用
SetEvent
函数将事件句柄设置为有信号状态。
使用
OSCond
的过程中存在一种需求,就是希望通知所有正在等待的用户事件已经完成,而
Signal()
函数每次只能通知一个用户,因此又开发了另外一个广播传信函数如下:
inline void OSCond::Broadcast()
{ //
提示:本函数相当循环调用
Signal()
函数
1 #ifdef __Win32__
2 UInt32 waitCount = fWaitCount
;
//
等待传信的用户数
3 for (UInt32 x = 0
;
x < waitCount
;
x++) //
循环为每个用户传信
4 {
5 BOOL theErr = ::SetEvent(fCondition)
;
//
设置事件句柄为有信号状态
6 Assert(theErr == TRUE)
;
7 }
//
此处略
…
}
Broadcast
首先统计所有等待传信的用户数(第
2
行),然后用一个循环为每个用户传信(第
3~7
)行。这种编程方法虽然不是很优雅(
elegant
),但是由于
Windows
平台上不支持广播传信功能(
Linux
和
Solaris
均支持),也只好如此。
3.1.2 OSThread Class
OSThread
是
DSS
中最重要的类之一,它封装并且定义了使用线程的方式,因此需要重点讨论。
OSThread
类的定义如下:
class OSThread
{
1 public:
//
必须在使用其他
OSThread
函数前调用该初始化函数
2 static void Initialize()
;
3 OSThread()
;
//
构造函数
4 virtual ~OSThread()
;
//
析构函数
//
子类继承该纯虚函数完成自己的工作
5 virtual void Entry() = 0
;
6 void Start()
;
//
启动线程
7 void Join()
;
//
等待线程运行完成后删除
8 void Detach()
;
//
使线程处于
fDetached
状态
9 static void ThreadYield()
;
//Windows
平台不用
10 static void Sleep(UInt32 inMsec)
;
//
让线程睡眠
…
11 private:
//
标识线程的状态
12 Bool16 fStopRequested:1
;
13 Bool16 fRunning:1
;
14 Bool16 fCancelThrown:1
;
15 Bool16 fDetached:1
;
16 Bool16 fJoined:1
;
…
17 static void CallEntry(OSThread* thread)
;
//
调用子类重载的虚函数
18 #ifdef __Win32__
//
使用
_beginghreadex
创建线程时的标准入口函数
19 static unsigned int WINAPI _Entry(LPVOID inThread)
;
20 #else
21 static void* _Entry(void* inThread)
;
//unix
下的入口函数
22 #endif
}
OSThread
封装了线程的基本功能,一个
OSThread
的实例代表一个线程。用户通过继承
OSThread
,并且重载其中的纯虚函数
Entry
(第
5
行),从而将自己的任务交给该线程运行。
OSThread
内部运行机制比较复杂,为此我们用图
3
所示的流程来描述其运行过程。
另外,
OSThread
对于线程的状态定义了一套完整的控制方法。当用户调用
start()
函数后,按照上图,最终将调用
CallEntry()
函数,而该函数在调用
Entry()
之前将线程设定为运行状态(
thread->fRunning = true
),当
Entry()
函数运行完后再设为非运行状态;在运行过程中,用户可以通过
StopAndWaitForThread()
、
join()
、
Detach()
以及
ThrowStopRequest()
等函数改变线程其他状态变量。
3.1.3 OSHashTable/OSQueue/OSHeap/OSRef Class
DSS
定义了几个通用的较为复杂的数据结构,它们都以类的方式封装。这些数据结构不但贯穿于
DSS
的所有源代码,而且由于其封装的十分好,读者可以在看懂源代码的基础上很容易的将它们从
DSS
的工程中抽取出来,构建自己的基础类库,为将来的开发工作打下良好的基础。另外,对这些基础数据结构源代码的研究将提高我们对于面向对象技术的掌握和领会。
最主要的数据结构有四种:哈希表(
OSHashTable
)、队列(
OSQueue
)、堆(
OSHeap
)和对象引用表(
OSRef
)。前三种是我们在编程中大量使用的数据结构,而对象引用表则是类似于
COM/DCOM
组件编程中
IUNKOWN
接口功能的数据结构,它首先为每个对象建立了一个字符串形式的
ID
,以便于通过这个
ID
找到对象(类似于
QueryInterface
);另外
OSRef
类还为每个对象实例建立了引用计数,只有一个对象不再被任何人引用,才可能被释放(类似于
AddRef
和
Release
)。
鉴于这几个类在结构上有相似之处,下面我们将分析
OSHashTable
的源代码,以便能够帮助读者更好的理解其他几个类。
OSHashTable
的代码如下:
template
class OSHashTable {
/*
提示:
OSHashTable
被设计成为一个类模版,两个输入参数分别为:
class T
:实际的对象类;
class K
:用于为
class T
计算哈希表键值的功能类。
*/
1 public:
2 OSHashTable( UInt32 size ) //
构造函数,入参是哈希表中对象的最大个数
3 {
4 fHashTable = new ( T*[size] )
;
//
申请分配
size
个哈希对象
class T
的空间
5 Assert( fHashTable )
;
6 memset( fHashTable, 0, sizeof(T*) * size )
;
//
初始化
7 fSize = size
;
/*
下面的代码决定用哪种方式为哈希表的键值计算索引;
如果哈希表的大小不是
2
的幂,只好采用对
fSize
求余的方法;
否则可以直接用掩码的方式,这种方式相对速度更快
*/
8 fMask = fSize - 1
;
9 if ((fMask & fSize) != 0) //fSize
不是
2
的幂
10 fMask = 0
;
11 fNumEntries = 0
;
//
当前对象数
12 }
13 ~OSHashTable() //
析构函数
14 {
15 delete [] fHashTable
;
//
释放空间
16 }
//
下面介绍向哈希表中添加一个
class T
对象的源代码
17 void Add( T* entry ) {
18 Assert( entry->fNextHashEntry == NULL )
;
/*
利用功能类
class K
,计算
class T
对象的哈希键值,其计算方法由用户在
class K
中定义
*/
19 K key( entry )
;
20 UInt32 theIndex = ComputeIndex( key.GetHashKey() )
;
//
利用键值计算索引
21 entry->fNextHashEntry = fHashTable[ theIndex ]
;
//
在新加对象中存储索引值
22 fHashTable[ theIndex ] = entry
;
//
将该对象插入到索引指定的位置
23 fNumEntries++
;
/
24 }
//
下面介绍从哈希表中删除一个
class T
对象的源代码
25 void Remove( T* entry )
26 {
//
首先从哈希表中找到待删除的对象
//1
、计算哈希键值和其对应的对象索引
27 key( entry )
;
28 UInt32 theIndex = ComputeIndex( key.GetHashKey() )
;
29 T* elem = fHashTable[ theIndex ]
;
30 T* last = NULL
;
/*2
、通过对象索引查找对象,如果不是要找的对象,接着找下一个,直到找到为止。这是因为,存放的时候就是按照这种模式计算索引的。
*/
31 while (elem && elem != entry) {
32 last = elem
;
33 elem = elem->fNextHashEntry
;
34 }
//
找到该对象,将其删除
35 if ( elem )
36 {
37 Assert(elem)
;
38 if (last)
39 last->fNextHashEntry = elem->fNextHashEntry
;
40 else //elem
在头部
41 fHashTable[ theIndex ] = elem->fNextHashEntry
;
42 elem->fNextHashEntry = NULL
;
43 fNumEntries--
;
44 }
45 }
//
下面介绍从哈希表中查找一个
class T
对象的方法
46 T* Map( K* key ) //
入参为哈希键值
47 {
48 UInt32 theIndex = ComputeIndex( key->GetHashKey() )
;
//
计算索引
49 T* elem = fHashTable[ theIndex ]
;
//
找到索引对应的对象
50 while (elem) {
51 K elemKey( elem )
;
52 if (elemKey =*key) //
检查是否找对
53 break
;
54 elem = elem->fNextHashEntry
;
//
如果不是,继续找下一个
55 }
56 return elem
;
57 }
//
以下略
…
}
以上介绍了哈希表的构造以及三种基本操作:添加、删除和查询。另外,
DSS
还定义了
OSHashTableIter
类用于枚举
OSHashTable
中的
class T
对象;其中主要的操作有
First
和
Next
等,限于篇幅,此处就不再详述。
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/你好赵伟/article/detail/891349
推荐阅读
article
【原创 附源码】
Flutter
安卓及
iOS
海外
登录
--
Apple
登录
最详细流程_
flutter
ap...
Flutter
集成
iOS
第三方
登录
_
flutter
apple
id
登录
flutter
apple
id
登录
...
赞
踩
article
Xcode
16
beta3
真机
调试找不到
Apple
Watch
的尝试解决_
xcode
没有看...
在本篇博文中,我们讨论了在
Xcode
中
真机
调试找不到
Apple
Watch
的尝试解决方法,希望能解大家燃眉之急!...
赞
踩
article
Apple
Watch
--
作为游戏
开发
者的你准备好了么? (上)_
apple
watch
游戏
开发
...
http://inpla.net/thread-8145-1-1.html
Apple
Watch
--
作为游戏
开发
者的...
赞
踩
article
Apple
Watch
开发
(二)--
Xcode
创建
项目及其结构_xcode15.0
创建
watch
项...
在上一篇文章中介绍了
Apple
Watch
的特点和app运行模式,那么这篇我们来看下如何利用
Xcode
创建
一个
Apple
...
赞
踩
article
apple
watch
真机开发第一步连接
xcode
详细教程,开启
watch
开发者
模式真的很坑啊啊啊啊...
1.首先先确保你的 Apple Watch 跟 你的 iPhone 已经配对完成2.用数据线连接你的 iPhone 到电...
赞
踩
article
Apple
Watch
开发初探_apple
watch
todo
list
...
今天苹果发布了iOS8.2 SDK Beta版和Xcode6.2 Beta版,其中最大的亮点就是就是
Watch
Kit,虽...
赞
踩
article
Apple
Watch
、
Watch
Kit
_什么是
watchkit
...
Apple
Watch
、
Watch
Kit
的简单介绍。_什么是
watchkit
什么是
watchkit
...
赞
踩
article
Apple
watch
开发指南(4) 配置你的
xcode
_
xcode
运行
调试真机
手表
...
1.png (36.15 KB, 下载次数: 0)下载附件4 小时前 上传创建
手表
端程序需要一个现有的ios程序。 在i...
赞
踩
article
什么!
Intel
/
AMD
/
Apple
Silicon
也能本地部署的
Llama
工具来了_
ollama
...
主流的LLM都需要通过CUDA才能高效的运行在本地,但是随着Github上出现了
Llama
.cpp这个神器,一切都改变了...
赞
踩
article
苹果公司
开发者
账号申请——
Apple
Developer
Program...
一、申请个邮箱(最好不要是QQ邮箱)二、打开苹果
开发者
网站1、滑动到页面底部,切换语音为中文2、点击Accont3、若没...
赞
踩
article
iOS
小技能:
苹果
开发者
续费
和
注册
教程(19年之前
通过
Apple
Developer
网站
完成
的
注...
前言如果您是
通过
Apple
Developer
网站
完成
的
注册
,
则不支持
通过
Apple
Developer
app
...
赞
踩
article
苹果(
APPLE
)
开发者
账号说明及注册流程(
99
美元
公司版/个人版及2
99
美元
企业
版)_
apple
...
APPLE
的政策是,要发布到APP STORE必须用
99
美元
的个人版或公司版Apple Developer Progra...
赞
踩
article
Darwin
-XNU
内核
架构浅析_
darwin
框架
...
苹果公司的产品有平板、手机、计算机和笔记本,手机和平板使用的是iOS,而计算机和笔记本使用的是macOS。Mach
内核
...
赞
踩
相关标签
flutter
ios
xcode
macos
mac
Apple Watch
iPhone
找不到设备
真机调试
apple watch
watchkit
iOS
Apple Watch App
Watch开发
Watch项目
ide
Apple Watch开发
智能手表
watchKit
llama
苹果开发者