You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MpLive/ZLMediaKit/3rdpart/ZLToolKit/tests/test_resourcePool.cpp

163 lines
6.4 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
*
* This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <csignal>
#include <iostream>
#include <random>
#include "Util/util.h"
#include "Util/logger.h"
#include "Util/ResourcePool.h"
#include "Thread/threadgroup.h"
#include <list>
using namespace std;
using namespace toolkit;
//程序退出标志 [AUTO-TRANSLATED:9ac79dfb]
// Program exit flag
bool g_bExitFlag = false;
class string_imp : public string{
public:
template<typename ...ArgTypes>
string_imp(ArgTypes &&...args) : string(std::forward<ArgTypes>(args)...){
DebugL << "创建string对象:" << this << " " << *this;
};
~string_imp(){
WarnL << "销毁string对象:" << this << " " << *this;
}
};
//后台线程任务 [AUTO-TRANSLATED:1411f16e]
// Background thread task
void onRun(ResourcePool<string_imp> &pool,int threadNum){
std::random_device rd;
while(!g_bExitFlag){
//从循环池获取一个可用的对象 [AUTO-TRANSLATED:10783ad7]
// Get an available object from the loop pool
auto obj_ptr = pool.obtain();
if(obj_ptr->empty()){
//这个对象是全新未使用的 [AUTO-TRANSLATED:9aaebe21]
// This object is brand new and unused
InfoL << "后台线程 " << threadNum << ":" << "obtain a emptry object!";
}else{
//这个对象是循环使用的 [AUTO-TRANSLATED:c13c04d6]
// This object is looped for reuse
InfoL << "后台线程 " << threadNum << ":" << *obj_ptr;
}
//标记该对象被本线程使用 [AUTO-TRANSLATED:4730d28a]
// Mark this object as used by the current thread
obj_ptr->assign(StrPrinter << "keeped by thread:" << threadNum );
//随机休眠,打乱循环使用顺序 [AUTO-TRANSLATED:313f439a]
// Random sleep to disrupt the loop usage order
usleep( 1000 * (rd()% 10));
obj_ptr.reset();//手动释放也可以注释这句代码。根据RAII的原理该对象会被自动释放并重新进入循环列队
usleep( 1000 * (rd()% 1000));
}
}
int main() {
//初始化日志 [AUTO-TRANSLATED:371bb4e5]
// Initialize log
Logger::Instance().add(std::make_shared<ConsoleChannel>());
Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
//大小为50的循环池 [AUTO-TRANSLATED:2ba6e2b3]
// Loop pool of size 50
ResourcePool<string_imp> pool;
pool.setSize(50);
//获取一个对象,该对象将被主线程持有,并且不会被后台线程获取并赋值 [AUTO-TRANSLATED:fa8654ed]
// Get an object that will be held by the main thread and will not be obtained and assigned by the background thread
auto reservedObj = pool.obtain();
//在主线程赋值该对象 [AUTO-TRANSLATED:a04a9b13]
// Assign the object in the main thread
reservedObj->assign("This is a reserved object , and will never be used!");
thread_group group;
//创建4个后台线程该4个线程模拟循环池的使用场景 [AUTO-TRANSLATED:a574c5f2]
// Create 4 background threads, these 4 threads simulate the usage scenario of a loop pool,
//理论上4个线程在同一时间最多同时总共占用4个对象 [AUTO-TRANSLATED:f2a82316]
// In theory, the 4 threads can occupy at most 4 objects at the same time
WarnL << "主线程打印:" << "开始测试,主线程已经获取到的对象应该不会被后台线程获取到:" << *reservedObj;
for(int i = 0 ;i < 4 ; ++i){
group.create_thread([i,&pool](){
onRun(pool,i);
});
}
//等待3秒钟此时循环池里面可用的对象基本上最少都被使用过一遍了 [AUTO-TRANSLATED:e5893625]
// Wait for 3 seconds, at this time, the objects available in the loop pool have been used at least once
sleep(3);
//但是由于reservedObj早已被主线程持有后台线程是获取不到该对象的 [AUTO-TRANSLATED:2c0e93ce]
// However, since reservedObj has been held by the main thread, the background threads cannot obtain the object
//所以其值应该尚未被覆盖 [AUTO-TRANSLATED:4cc91f7b]
// So its value should not have been overwritten
WarnL << "主线程打印: 该对象还在被主线程持有,其值应该保持不变:" << *reservedObj;
//获取该对象的引用 [AUTO-TRANSLATED:ca198d5f]
// Get a reference to the object
auto &objref = *reservedObj;
//显式释放对象,让对象重新进入循环列队,这时该对象应该会被后台线程持有并赋值 [AUTO-TRANSLATED:8d97a1af]
// Explicitly release the object, allowing it to re-enter the loop queue, at this time the object should be held and assigned by the background thread
reservedObj.reset();
WarnL << "主线程打印: 已经释放该对象,它应该会被后台线程获取到并被覆盖值";
//再休眠3秒让reservedObj被后台线程循环使用 [AUTO-TRANSLATED:4830df93]
// Sleep for another 3 seconds, allowing reservedObj to be looped and used by the background thread
sleep(3);
//这时reservedObj还在循环池内引用应该还是有效的但是值应该被覆盖了 [AUTO-TRANSLATED:1323f66e]
// At this time, reservedObj is still in the loop pool, the reference should still be valid, but the value should have been overwritten
WarnL << "主线程打印:对象已被后台线程赋值为:" << objref << endl;
{
WarnL << "主线程打印:开始测试主动放弃循环使用功能";
List<decltype(pool)::ValuePtr> objlist;
for (int i = 0; i < 8; ++i) {
reservedObj = pool.obtain();
string str = StrPrinter << i << " " << (i % 2 == 0 ? "此对象将脱离循环池管理" : "此对象将回到循环池");
reservedObj->assign(str);
reservedObj.quit(i % 2 == 0);
objlist.emplace_back(reservedObj);
}
}
sleep(3);
//通知后台线程退出 [AUTO-TRANSLATED:dbeda936]
// Notify background thread to exit
g_bExitFlag = true;
//等待后台线程退出 [AUTO-TRANSLATED:49b72af6]
// Wait for background thread to exit
group.join_all();
return 0;
}