提交 83b78ef9 编写于 作者: 独孤过's avatar 独孤过

update from v2.2.1 to v2.2.2

上级 d4f53515
......@@ -20,7 +20,7 @@ int main()
cout << thread.getID() << endl;
thread.configure([] \
{ cout << "solifree" << endl; }, nullptr);
{ cout << "Solifree" << endl; }, nullptr);
cout << boolalpha << thread.notify() << endl;
return EXIT_SUCCESS;
}
#define ETERFREE
#define BOOST
#define THREAD
#define ASIO
//#define FILE_STREAM
//#define FILE_SYSTEM
#if defined THREAD
#include "Common.cpp"
#if defined ETERFREE
#include "ThreadPool.h"
#elif defined BOOST
#include <boost/threadpool.hpp>
#elif defined ASIO
#ifdef _WIN32
#include <WinSock2.h>
#endif // _WIN32
#include "Common.cpp"
#include <boost/asio.hpp>
#endif
#include <chrono>
......@@ -17,124 +23,88 @@
#include <atomic>
#include <thread>
#ifdef FILE_STREAM
#include <fstream>
#ifdef FILE_SYSTEM
#include <filesystem>
#endif // FILE_SYSTEM
#endif // FILE_STREAM
#ifdef _WIN32
#include <Windows.h>
#pragma comment(lib, "WinMM.Lib")
#endif // _WIN32
#if defined ETERFREE
using ThreadPool = Eterfree::ThreadPool;
#elif defined BOOST
#if defined THREAD
using ThreadPool = boost::threadpool::thread_pool<>;
#elif defined ASIO
using ThreadPool = boost::asio::thread_pool;
#endif
static constexpr auto SLEEP_TIME = std::chrono::milliseconds(1);
static constexpr std::chrono::nanoseconds::rep SLEEP_TIME = 1000000;
static std::atomic_ulong counter = 0;
static auto getConcurrency() noexcept
{
auto concurrency = std::thread::hardware_concurrency();
return concurrency > 0 ? \
concurrency : static_cast<decltype(concurrency)>(1);
}
static void task()
{
for (volatile auto index = 0UL; \
index < 10000UL; ++index);
#ifdef _WIN32
constexpr UINT PERIOD = 1;
auto result = ::timeBeginPeriod(PERIOD);
if (result != TIMERR_NOERROR)
std::cerr << "timeBeginPeriod error " \
<< result << std::endl;
#endif // _WIN32
std::this_thread::sleep_for(SLEEP_TIME);
#ifdef _WIN32
result = ::timeEndPeriod(PERIOD);
if (result != TIMERR_NOERROR)
std::cerr << "timeEndPeriod error " \
<< result << std::endl;
#endif // _WIN32
sleepFor(SLEEP_TIME);
counter.fetch_add(1, \
std::memory_order_relaxed);
}
#if defined ETERFREE
#if defined THREAD
static void execute(ThreadPool& _threadPool)
{
auto proxy = _threadPool.getProxy();
for (auto index = 0UL; index < 50000UL; ++index)
proxy.pushTask(task);
_threadPool.schedule(task);
ThreadPool::TaskQueue taskQueue;
for (auto index = 0UL; index < 50000UL; ++index)
taskQueue.push_back(task);
proxy.pushTask(std::move(taskQueue));
_threadPool.schedule(task);
}
static void terminate(ThreadPool&& _threadPool)
{
_threadPool.clearTask();
auto threadPool(std::forward<ThreadPool>(_threadPool));
(void)threadPool;
}
#elif defined BOOST
static auto getConcurrency() noexcept
{
auto concurrency = std::thread::hardware_concurrency();
return concurrency > 0 ? \
concurrency : static_cast<decltype(concurrency)>(1);
}
#elif defined ASIO
static void execute(ThreadPool& _threadPool)
{
for (auto index = 0UL; index < 50000UL; ++index)
_threadPool.schedule(task);
boost::asio::post(_threadPool, task);
for (auto index = 0UL; index < 50000UL; ++index)
_threadPool.schedule(task);
boost::asio::post(_threadPool, task);
}
static void terminate(ThreadPool&& _threadPool)
{
auto threadPool(std::forward<ThreadPool>(_threadPool));
(void)threadPool;
_threadPool.join();
}
#endif
int main()
{
using namespace std::chrono;
using std::cout, std::endl;
constexpr auto load = []() noexcept
{ return counter.load(std::memory_order_relaxed); };
#ifdef FILE_STREAM
constexpr auto FILE = "ThreadPool.txt";
constexpr auto FILE = "Boost.txt";
#ifdef FILE_SYSTEM
std::filesystem::remove(FILE);
if (std::filesystem::exists(FILE))
std::filesystem::remove(FILE);
#endif // FILE_SYSTEM
std::ofstream ofs(FILE, std::ios::app);
auto os = cout.rdbuf(ofs.rdbuf());
#endif // FILE_STREAM
#if defined ETERFREE
ThreadPool threadPool;
#elif defined BOOST
ThreadPool threadPool(getConcurrency());
#endif
auto begin = system_clock::now();
execute(threadPool);
......
#include "Common.h"
#include <string>
#include <iostream>
#include <thread>
#ifdef _WIN32
#include <Windows.h>
#pragma comment(lib, "WinMM.Lib")
#endif // _WIN32
void sleepFor(std::chrono::nanoseconds::rep _duration)
{
if (_duration <= 0) return;
#ifdef _WIN32
constexpr UINT PERIOD = 1;
auto result = ::timeBeginPeriod(PERIOD);
if (result != TIMERR_NOERROR)
{
std::string buffer = "timeBeginPeriod error ";
buffer += std::to_string(result);
std::cerr << buffer << std::endl;
}
#endif // _WIN32
auto duration = std::chrono::nanoseconds(_duration);
std::this_thread::sleep_for(duration);
#ifdef _WIN32
result = ::timeEndPeriod(PERIOD);
if (result != TIMERR_NOERROR)
{
std::string buffer = "timeEndPeriod error ";
buffer += std::to_string(result);
std::cerr << buffer << std::endl;
}
#endif // _WIN32
}
#pragma once
//#define FILE_STREAM
//#define FILE_SYSTEM
#include <chrono>
#ifdef FILE_STREAM
#include <fstream>
#ifdef FILE_SYSTEM
#include <filesystem>
#endif // FILE_SYSTEM
#endif // FILE_STREAM
void sleepFor(std::chrono::nanoseconds::rep _duration);
#include "Common.h"
#include "ThreadPool.h"
#include <chrono>
#include <cstdlib>
#include <utility>
#include <iostream>
#include <atomic>
#include <thread>
using ThreadPool = Eterfree::ThreadPool;
static constexpr std::chrono::nanoseconds::rep SLEEP_TIME = 1000000;
static std::atomic_ulong counter = 0;
static void task()
{
for (volatile auto index = 0UL; \
index < 10000UL; ++index);
sleepFor(SLEEP_TIME);
counter.fetch_add(1, \
std::memory_order_relaxed);
}
static void execute(ThreadPool& _threadPool)
{
auto proxy = _threadPool.getProxy();
for (auto index = 0UL; index < 50000UL; ++index)
proxy.pushTask(task);
ThreadPool::TaskQueue taskQueue;
for (auto index = 0UL; index < 50000UL; ++index)
taskQueue.push_back(task);
proxy.pushTask(std::move(taskQueue));
}
static void terminate(ThreadPool&& _threadPool)
{
_threadPool.clearTask();
auto threadPool(std::forward<ThreadPool>(_threadPool));
(void)threadPool;
}
int main()
{
using namespace std::chrono;
using std::cout, std::endl;
constexpr auto load = []() noexcept
{ return counter.load(std::memory_order_relaxed); };
#ifdef FILE_STREAM
constexpr auto FILE = "Eterfree.txt";
#ifdef FILE_SYSTEM
if (std::filesystem::exists(FILE))
std::filesystem::remove(FILE);
#endif // FILE_SYSTEM
std::ofstream ofs(FILE, std::ios::app);
auto os = cout.rdbuf(ofs.rdbuf());
#endif // FILE_STREAM
ThreadPool threadPool;
auto begin = system_clock::now();
execute(threadPool);
std::this_thread::sleep_for(seconds(10));
auto count = load();
auto end = system_clock::now();
auto duration = duration_cast<milliseconds>(end - begin);
cout << "任务数量:" << count << endl;
cout << "执行时间:" << duration.count() << endl;
#ifdef FILE_STREAM
cout << endl;
cout.rdbuf(os);
#endif // FILE_STREAM
terminate(std::move(threadPool));
cout << "任务总数:" << load() << endl;
return EXIT_SUCCESS;
}
#include "Common.cpp"
#define ETERFREE
#define BOOST
#if defined ETERFREE
#include "Eterfree.cpp"
#elif defined BOOST
#include "Boost.cpp"
#endif
......@@ -5,11 +5,11 @@
#define TEST THREAD_POOL
#if TEST == THREAD_POOL
#include "test1.cpp"
#include "ThreadPool/test.cpp"
#elif TEST == THREAD
#include "test2.cpp"
#include "Thread/test.cpp"
#elif TEST == DOUBLE_QUEUE
#include "test3.cpp"
#include "DoubleQueue/test.cpp"
#endif
......@@ -239,8 +239,7 @@ template <typename _Clock, typename _Duration>
bool Condition<_Size>::wait_until(const std::chrono::time_point<_Clock, _Duration>& _absolute)
{
std::unique_lock lock(_mutex);
return valid() \
&& _condition.wait_until(lock, _absolute) == std::cv_status::no_timeout;
return valid() && _condition.wait_until(lock, _absolute) == std::cv_status::no_timeout;
}
template <typename _Size>
......
......@@ -94,7 +94,7 @@ auto Thread::move(Thread& _left, Thread&& _right) \
-> DataType
{
std::lock_guard leftLock(_left._mutex);
auto data = _left._data;
auto data = std::move(_left._data);
std::lock_guard rightLock(_right._mutex);
_left._data = std::move(_right._data);
......@@ -195,6 +195,27 @@ Thread::Thread() : \
create();
}
// 默认移动构造函数
Thread::Thread(Thread&& _another) noexcept
{
try
{
std::lock_guard lock(_another._mutex);
this->_data = std::move(_another._data);
}
catch (std::exception&) {}
}
// 默认析构函数
Thread::~Thread() noexcept
{
try
{
destroy();
}
catch (std::exception&) {}
}
// 默认移动赋值运算符函数
Thread& Thread::operator=(Thread&& _another)
{
......
......@@ -3,7 +3,7 @@
* 语言标准:C++17
*
* 创建日期:2017年09月22日
* 更新日期:2023年02月07
* 更新日期:2023年08月24
*
* 摘要
* 1. 线程类Thread定义于此文件,实现于Thread.cpp。
......@@ -22,7 +22,7 @@
* 作者:许聪
* 邮箱:solifree@qq.com
*
* 版本:v2.2.1
* 版本:v2.2.2
* 变化
* v2.0.1
* 1.运用Condition的宽松策略,提升激活线程的效率。
......@@ -39,6 +39,9 @@
* 3.判断获取的任务是否有效,以防止线程泄漏。
* v2.2.1
* 1.修复移动赋值运算符函数的资源泄漏问题。
* v2.2.2
* 1.优化移动语义。
* 2.确保移动构造函数和析构函数的异常安全性。
*/
#pragma once
......@@ -105,14 +108,10 @@ public:
Thread(const Thread&) = delete;
// 默认移动构造函数
Thread(Thread&& _another)
{
std::lock_guard lock(_another._mutex);
this->_data = std::move(_another._data);
}
Thread(Thread&& _another) noexcept;
// 默认析构函数
~Thread() { destroy(); }
~Thread() noexcept;
// 删除默认复制赋值运算符函数
Thread& operator=(const Thread&) = delete;
......
......@@ -258,7 +258,7 @@ auto ThreadPool::move(ThreadPool& _left, \
ThreadPool&& _right) -> DataType
{
std::lock_guard leftLock(_left._mutex);
auto data = _left._data;
auto data = std::move(_left._data);
std::lock_guard rightLock(_right._mutex);
_left._data = std::move(_right._data);
......@@ -437,6 +437,29 @@ ThreadPool::ThreadPool(SizeType _size, \
create(load(), _capacity);
}
// 默认移动构造函数
ThreadPool::ThreadPool(ThreadPool&& _another) noexcept
{
try
{
std::lock_guard lock(_another._mutex);
this->_data = std::move(_another._data);
}
catch (std::exception&) {}
}
// 默认析构函数
ThreadPool::~ThreadPool() noexcept
{
try
{
// 数据非空才进行销毁,以支持移动语义
if (auto data = load())
destroy(std::move(data));
}
catch (std::exception&) {}
}
// 默认移动赋值运算符函数
ThreadPool& ThreadPool::operator=(ThreadPool&& _another)
{
......@@ -451,7 +474,7 @@ ThreadPool& ThreadPool::operator=(ThreadPool&& _another)
}
// 获取线程池容量
ThreadPool::SizeType ThreadPool::getCapacity() const
auto ThreadPool::getCapacity() const -> SizeType
{
auto data = load();
return data ? data->getCapacity() : 0;
......@@ -470,21 +493,21 @@ bool ThreadPool::setCapacity(SizeType _capacity)
}
// 获取总线程数量
ThreadPool::SizeType ThreadPool::getTotalSize() const
auto ThreadPool::getTotalSize() const -> SizeType
{
auto data = load();
return data ? data->getTotalSize() : 0;
}
// 获取闲置线程数量
ThreadPool::SizeType ThreadPool::getIdleSize() const
auto ThreadPool::getIdleSize() const -> SizeType
{
auto data = load();
return data ? data->getIdleSize() : 0;
}
// 获取任务数量
ThreadPool::SizeType ThreadPool::getTaskSize() const
auto ThreadPool::getTaskSize() const -> SizeType
{
auto data = load();
return data ? data->_taskQueue->size() : 0;
......@@ -530,7 +553,8 @@ bool ThreadPool::pushTask(TaskQueue&& _taskQueue)
bool ThreadPool::popTask(TaskQueue& _taskQueue)
{
auto data = load();
return data && data->_taskQueue->pop(_taskQueue);
return data \
&& data->_taskQueue->pop(_taskQueue);
}
// 清空任务
......@@ -541,7 +565,8 @@ void ThreadPool::clearTask()
}
// 获取代理
ThreadPool::Proxy ThreadPool::getProxy() const
auto ThreadPool::getProxy() const \
-> Proxy
{
return load();
}
......
......@@ -3,7 +3,7 @@
* 语言标准:C++17
*
* 创建日期:2017年09月22日
* 更新日期:2023年02月07
* 更新日期:2023年08月24
*
* 摘要
* 1.线程池类ThreadPool定义于此文件,实现于ThreadPool.cpp。
......@@ -21,7 +21,7 @@
* 作者:许聪
* 邮箱:solifree@qq.com
*
* 版本:v2.2.1
* 版本:v2.2.2
* 变化
* v2.0.1
* 1.运用Condition的宽松策略,提升激活守护线程的性能。
......@@ -44,6 +44,9 @@
* 2.设置线程池容量函数返回合理值。
* v2.2.1
* 1.修复移动赋值运算符函数的资源泄漏问题。
* v2.2.2
* 1.优化移动语义。
* 2.确保移动构造函数和析构函数的异常安全性。
*/
#pragma once
......@@ -121,19 +124,10 @@ public:
ThreadPool(const ThreadPool&) = delete;
// 默认移动构造函数
ThreadPool(ThreadPool&& _another)
{
std::lock_guard lock(_another._mutex);
this->_data = std::move(_another._data);
}
ThreadPool(ThreadPool&& _another) noexcept;
// 默认析构函数
~ThreadPool()
{
// 数据非空才进行销毁,以支持移动语义
if (auto data = load())
destroy(std::move(data));
}
~ThreadPool() noexcept;
// 删除默认复制赋值运算符函数
ThreadPool& operator=(const ThreadPool&) = delete;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册