线程池 | Any、Semaphore类
线程池 | Any、Semaphore类
1.Any类
1 | //Any类 表示可以接受任意数据的类型 |
把Any类的拷贝构造和拷贝赋值都delet是因为私有成员base_是unique_ptr,unique_ptr的拷贝构造和拷贝赋值是delete的。
为什么 Any
类可以承接所有的类型
这个 Any
类可以承接所有类型的原因主要在于它使用了模板和多态的技术。
模板的使用:
1 | template <typename T> |
- 这个构造函数是一个模板函数,这意味着它可以接受任何类型T的数据作为参数。当你使用 Any类创建对象时,例如:
Any a(5);
这里T
是int
,编译器会实例化一个Any<int>
的构造函数,它会将5
存储在Derive<int>
类型的对象中。Any b(std::string("hello"));
这里T
是std::string
,编译器会实例化一个Any<std::string>
的构造函数,它会将"hello"
存储在Derive<std::string>
类型的对象中。
多态的使用:
1 | class Base |
Any
类包含一个私有成员base_
,它是一个std::unique_ptr<Base>
类型的指针,Base
是一个基类,并且有一个模板派生类Derive<T>
继承自Base
。- 在存储数据时,使用
std::make_unique<Derive<T>>(data)
创建一个Derive<T>
的对象,并将其存储在base_
中。由于Derive<T>
是从Base
派生的,所以可以将Derive<T>
的指针存储在std::unique_ptr<Base>
中,这利用了多态性。
工作流程解释
假设你创建了一个 Any
对象,如 Any a(5);
:
- 调用
Any
的模板构造函数,T
是int
,编译器会生成一个Any<int>
的构造函数。 - 这个构造函数会调用
std::make_unique<Derive<int>>(5)
,创建一个Derive<int>
类型的对象,该对象存储了int
类型的数据。 - 存储的数据被存储在
Derive<int>
的data_
成员中。 - 这个
Derive<int>
对象的指针被存储在base_
中,由于Derive<int>
继承自Base
,所以可以使用std::unique_ptr<Base>
来存储它。
如何存储不同类型的数据
- 当你存储不同类型的数据时,
Any
类会为每个类型创建一个对应的Derive<T>
派生类实例,通过多态将这些派生类对象存储在base_
中。 - 每个
Derive<T>
实例都存储了具体类型的数据,并且都可以通过base_
指针来管理,因为它们都继承自Base
。
提取数据时的类型检查
1 | template<typename T> |
- 当你调用
cast_
方法时,使用dynamic_cast<Derive<T>*>(base_.get())
尝试将存储的对象转换为Derive<T>*
类型。 dynamic_cast
会在运行时检查存储的对象是否真的是Derive<T>
类型。如果是,它将返回Derive<T>
的指针,你可以访问data_
成员来获取存储的数据;如果不是,dynamic_cast
将返回nullptr
,此时会抛出异常,因为存储的对象类型与你想要提取的类型不匹配。
通过这种方式,Any
类利用模板和多态性可以存储和管理不同类型的数据,但在使用 cast_
方法时,需要确保存储的对象类型和提取时指定的类型一致,否则会引发异常。
总结
- 模板允许
Any
类接受任何类型的数据,因为对于不同类型的数据,会生成相应的Derive<T>
实例。 - 多态允许将这些不同类型的
Derive<T>
实例存储在base_
指针中,因为它们都继承自Base
。 cast_
方法使用dynamic_cast
进行运行时类型检查,以确保提取的数据类型与存储的数据类型匹配。
2.Semaphore类
通过条件变量+互斥锁来实现信号量
1 | //实现一个信号量类 |
互斥锁是只有0和1的资源计数器,一个线程拿了以后,资源计数器-1,变为0,那么其他线程不可以拿了就
信号量就是资源数量可以自定义的资源计数器,我们传给limit是多少,那就是多少
wait方法
1 | //获取一个信号量资源 |
获取互斥锁,然后条件变量阻塞等待资源计数器大于0,只有1.被唤醒后,2.拿到锁并且3.满足条件之后才会继续执行。一旦继续执行,那就是代表当前线程满足了条件,就是代表拿到了资源,我们的资源就得要–
post方法
1 | //增加一个信号量资源 |
获取互斥锁,post说明我们用完资源了,资源计数器++。我们不知道自己拿着的资源是不是最后一个,所以只要放回去资源,就要通知其他的线程有资源放回去了,让他们来使用。
想要了解更多信号量的读者:实现线程同步的方法-CSDN博客
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Darlingの妙妙屋!
评论