From 0aa63205ccdd9a57f7fe2d1fea8fbf23633e0ebf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 03:19:37 +0000 Subject: [PATCH 1/4] docs: Added README."en".md translation via https://github.com/dephraiim/translate-readme --- README.en.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 README.en.md diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..c373011 --- /dev/null +++ b/README.en.md @@ -0,0 +1,56 @@ +# Cpp-Examples + +- [Simplified Chinese](README.md) +- [English](README.en.md) + +## Code structure + +1. [Algorithm](/Algorithm/) + 1. [Search](/Algorithm/Search/search.hpp)——Implementation of various search algorithms, as well as unit testing and performance testing based on Google benchmark; + 1. [std_search_examples](/Algorithm/Search/std_search_examples.cc)——Example of search algorithm in stl; + 2. [Sort](/Algorithm/Sort/sort.hpp)——Implementation of various sorting algorithms, as well as unit testing and performance testing based on Google benchmark; + 1. [std_sort_examples](/Algorithm/Sort/std_sort_examples.cc)——Example of sorting algorithm in stl; +2. [BinaryTree](/BinaryTree/binarytree.hpp)——Related operations of binary trees, insert, remove, find, and print; +3. [Breakpad](/Breakpad/breakpad.hpp)——A simple package of google breakpad; +4. [Byte order](/ByteOrder/byteorder.hpp)——Judge the endianness of the system; +5. [Client](/Client/client.cpp)——A simple Linux select socket client; +6. [CountDownLatch](/CountDownLatch/countdownlatch.hpp)——Simple countdown latch (std::latch c++20) implemented using std::mutex and std::condition_variable; +7. [Crashpad](/Crashpad/crashpad.hpp)——Simple encapsulation of google crashpad; +8. [Curl](/Curl/)——Simple use of curl; +9. [TcpClient](/Curl/tcpclient.hpp)——Simple tcp client implemented using curl; +10. [HttpClient](/Curl/httpclient.hpp)——Simple http synchronization client implemented using curl; +11. [HttpClientAsync](/Curl/httpclient_async.hpp)——Simple http asynchronous client implemented using curl; +12. [Design pattern](/DesignPattern)——Some examples of design patterns; + 1. [Factory](/DesignPattern/Factory/factory.hpp)——Factory model; + 2. [MVC](/DesignPattern/MVC/model.hpp)——MVC mode; + 3. [Observer](/DesignPattern/Observer/observer.hpp)——Observer mode; + 4. [Singleton](/DesignPattern/Singleton/singleton.hpp)——Singleton mode; +13. [GlobMatch](/GlobMatch/globmatcher.hpp)——Simple implementation of glob pattern matching; +14. [Glog](/Glog/main.cc)——Google glog example; +15. [Icmp](/Icmp/icmp.hpp)——Simple encapsulation of linux icmp protocol; +16. [LinkedList](/LinkedList/linkedlist.hpp)——Related operations of linked lists, insert, remove, invert, and print; +17. [Memcpy](/Memcpy/memcpy.hpp)——`memcpy`Function implementation; +18. [Is a monitor](/MonitorDir/monitordir.hpp)——windows(`ReadDirectoryChangesW`),macos(`FSEvents`) and linux(`fanotify`and`inotify`) Simple examples of directory monitoring; + 1. `fanotify`Used in`global`Mode, in`fanotify_mark`Join`FAN_MARK_FILESYSTEM`(need`CAP_SYS_ADMIN`ability, that is, root permissions)`flag`, All events on the specified file system can be monitored, and then the required events can be filtered according to the specified monitored folder directory. This function is more`inotify`More powerful; + 1. Get the upper path where the event file is located, using`open_by_handle_at`This method will appear under ordinary users`Operation not permitted`Error, also required`CAP_SYS_ADMIN`Ability, that is, root permissions; + 2. It is recommended to use root permissions to run. If you must run it under normal users, it is recommended to use it.`inotify`Instead`fanotify`, open a monitoring file descriptor (`fd`) cannot be achieved`subtree`monitor; +19. [MonitorDir_EFSW](/MonitorDir_EFSW/main.cc)——A simple example of directory monitoring implemented using efsw; +20. [OpenSSL](/OpenSSL)——Some examples of openssl; + 1. [aes](/OpenSSL/openssl_aes.cc)——Aes encryption and decryption example; + 2. [base64](/OpenSSL/openssl_base64.cc)——Example of base64 encoding and decoding; + 3. [hash](/OpenSSL/openssl_hash.cc)——Sha256 example; + 4. [hmac](/OpenSSL/openssl_hmac.cc)——The example of hmac; + 5. [pem](/OpenSSL/openssl_pem.cc)——Example of pem format; + 6. [rsa](/OpenSSL/openssl_rsa.cc)——Example of rsa encryption and decryption; + 7. [SM4](/OpenSSL/openssl_sm4.cc)——Example of sm4 encryption and decryption; + 8. [Dirt 09](/OpenSSL/openssl_x509.cc)——Example of x509 certificate; + 9. [bash](/OpenSSL/openssl_bash.sh)——Example of the openssl command line; +21. [SafeCallback](/SafeCallback/safecallback.hpp)——Implementation of life cycle safe callback function, reference[muduo WeakCallback](https://github.com/chenshuo/muduo/blob/cpp17/muduo/base/WeakCallback.h); +22. [Server](/Server)——Some examples of linux server; + 1. [server_epoll](/Server/server_epoll.cc)——The example of epoll; + 2. [server_poll](/Server/server_poll.cc)——A example of poll; + 3. [server_select](/Server/server_select.cc)——Select example; +23. [SpinMutex](/SpinMutex)——Simple mutex and spin lock implemented using std::atomic_flag; +24. [Thread](/Thread/)——Thread class based on std::jthread implementation, including thread pool (`Apple Clang`Not supported); + 1. [Thread](/Thread/thread.hpp)——Thread class; + 2. [ThreadPool](/Thread/threadpool.hpp)——Thread pool; From 0f49a1b245b37ed009f97461b0f5c80264d012cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=AE=E7=94=9F=E8=8B=A5=E6=A2=A6?= <1070753498@qq.com> Date: Tue, 6 May 2025 13:30:43 +0800 Subject: [PATCH 2/4] =?UTF-8?q?[=E9=87=8D=E6=9E=84macOS=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E5=AE=9E=E7=8E=B0]=EF=BC=9AmacOS=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E7=9B=91=E6=8E=A7=E5=AE=9E=E7=8E=B0=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8F=8A=E4=BA=8B=E4=BB=B6=E6=A0=87=E5=BF=97=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构事件标志处理逻辑: 将eventFlagsToString改为拼接所有匹配的事件标志,并增加原始值日志输出 - 改用GCD队列管理事件流: 使用FSEventStreamSetDispatchQueue替代CFRunLoop调度机制,提升代码健壮性 - 优化线程管理机制: 移除独立监控线程实现,通过dispatch_queue自动管理事件处理线程 - 完善资源释放流程: 在事件流创建失败时及时释放CF对象,避免内存泄漏 - 增强状态跟踪可靠性: 使用原子变量m_isRunning替代普通bool类型,确保多线程状态同步 - 修正日志输出格式: 修复路径输出缺少空格的拼写问题,提升日志可读性 - 调整事件流参数配置: 将事件延迟间隔从3秒改为立即响应,提升监控实时性 --- MonitorDir/monitordir_mac.cc | 139 +++++++++++++++++------------------ 1 file changed, 69 insertions(+), 70 deletions(-) diff --git a/MonitorDir/monitordir_mac.cc b/MonitorDir/monitordir_mac.cc index 8541507..ee56f9e 100644 --- a/MonitorDir/monitordir_mac.cc +++ b/MonitorDir/monitordir_mac.cc @@ -3,83 +3,90 @@ #include #include -#include std::string eventFlagsToString(FSEventStreamEventFlags eventFlags) { + std::cout << "FSEventStreamEventFlags: " << std::to_string(eventFlags) << std::endl; + + std::string text; if ((eventFlags & kFSEventStreamEventFlagNone) != 0U) { - return "None: "; + text += "None"; } if ((eventFlags & kFSEventStreamEventFlagMustScanSubDirs) != 0U) { - return "MustScanSubDirs: "; + text += "MustScanSubDirs "; } if ((eventFlags & kFSEventStreamEventFlagUserDropped) != 0U) { - return "UserDropped: "; + text += "UserDropped "; } if ((eventFlags & kFSEventStreamEventFlagKernelDropped) != 0U) { - return "KernelDropped: "; + text += "KernelDropped "; } if ((eventFlags & kFSEventStreamEventFlagEventIdsWrapped) != 0U) { - return "EventIdsWrapped: "; + text += "EventIdsWrapped "; } if ((eventFlags & kFSEventStreamEventFlagHistoryDone) != 0U) { - return "HistoryDone: "; + text += "HistoryDone "; } if ((eventFlags & kFSEventStreamEventFlagRootChanged) != 0U) { - return "RootChanged: "; + text += "RootChanged "; } if ((eventFlags & kFSEventStreamEventFlagMount) != 0U) { - return "Mount: "; + text += "Mount "; } if ((eventFlags & kFSEventStreamEventFlagUnmount) != 0U) { - return "Unmount: "; + text += "Unmount "; } if ((eventFlags & kFSEventStreamEventFlagItemCreated) != 0U) { - return "Created: "; + text += "Created "; } if ((eventFlags & kFSEventStreamEventFlagItemRemoved) != 0U) { - return "Removed: "; + text += "Removed "; } if ((eventFlags & kFSEventStreamEventFlagItemInodeMetaMod) != 0U) { - return "InodeMetaMod: "; + text += "InodeMetaMod "; } if ((eventFlags & kFSEventStreamEventFlagItemRenamed) != 0U) { - return "Renamed: "; + text += "Renamed "; } if ((eventFlags & kFSEventStreamEventFlagItemModified) != 0U) { - return "Modified: "; + text += "Modified "; } if ((eventFlags & kFSEventStreamEventFlagItemFinderInfoMod) != 0U) { - return "FinderInfoMod: "; + text += "FinderInfoMod "; } if ((eventFlags & kFSEventStreamEventFlagItemChangeOwner) != 0U) { - return "ChangeOwner: "; + text += "ChangeOwner "; } if ((eventFlags & kFSEventStreamEventFlagItemXattrMod) != 0U) { - return "XattrMod: "; + text += "XattrMod "; } if ((eventFlags & kFSEventStreamEventFlagItemIsFile) != 0U) { - return "IsFile: "; + text += "IsFile "; } if ((eventFlags & kFSEventStreamEventFlagItemIsDir) != 0U) { - return "IsDir: "; + text += "IsDir "; } if ((eventFlags & kFSEventStreamEventFlagItemIsSymlink) != 0U) { - return "IsSymlink: "; + text += "IsSymlink "; } if ((eventFlags & kFSEventStreamEventFlagOwnEvent) != 0U) { - return "OwnEvent: "; + text += "OwnEvent "; } if ((eventFlags & kFSEventStreamEventFlagItemIsHardlink) != 0U) { - return "IsHardlink: "; + text += "IsHardlink "; } if ((eventFlags & kFSEventStreamEventFlagItemIsLastHardlink) != 0U) { - return "IsLastHardlink: "; + text += "IsLastHardlink "; } if ((eventFlags & kFSEventStreamEventFlagItemCloned) != 0U) { - return "Cloned: "; + text += "Cloned "; + } + if (text.empty()) { + text = "Unknown " + std::to_string(eventFlags) + ""; + } else { + text += ": "; } - return "Unknown " + std::to_string(eventFlags) + ": "; + return text; } class MonitorDir::MonitorDirPrivate @@ -101,7 +108,7 @@ class MonitorDir::MonitorDirPrivate // auto *monitorDir = static_cast(clientCallBackInfo); char **paths = static_cast(eventPaths); if (paths == nullptr) { - std::cerr << "Error: paths is null." << std::endl; + std::cerr << "Errorpaths is null." << std::endl; return; } for (size_t i = 0; i < numEvents; ++i) { @@ -113,54 +120,55 @@ class MonitorDir::MonitorDirPrivate } } - void monitor() + bool monitor() { - std::cout << "addWatch: " << dir << std::endl; - CFStringRef pathToWatch = CFStringCreateWithCString(kCFAllocatorDefault, - dir.c_str(), - kCFStringEncodingUTF8); - CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorDefault, - reinterpret_cast(&pathToWatch), - 1, - nullptr); + std::cout << "addWatch" << dir << std::endl; + auto pathToWatch = CFStringCreateWithCString(kCFAllocatorDefault, + dir.c_str(), + kCFStringEncodingUTF8); + auto pathsToWatch = CFArrayCreate(kCFAllocatorDefault, + reinterpret_cast(&pathToWatch), + 1, + nullptr); FSEventStreamContext context{0, this, nullptr, nullptr, nullptr}; - FSEventStreamRef stream = FSEventStreamCreate(kCFAllocatorDefault, - monitorCallback, - &context, - pathsToWatch, - kFSEventStreamEventIdSinceNow, - 3, - kFSEventStreamCreateFlagFileEvents); - runLoop = CFRunLoopGetCurrent(); - FSEventStreamScheduleWithRunLoop(stream, runLoop, kCFRunLoopDefaultMode); + stream = FSEventStreamCreate(kCFAllocatorDefault, + monitorCallback, + &context, + pathsToWatch, + kFSEventStreamEventIdSinceNow, + 0., + kFSEventStreamCreateFlagFileEvents); + if (stream == nullptr) { + std::cerr << "Failed to create FSEventStream" << std::endl; + CFRelease(pathsToWatch); + CFRelease(pathToWatch); + return false; + } + auto queue = dispatch_queue_create(nullptr, nullptr); + FSEventStreamSetDispatchQueue(stream, queue); FSEventStreamStart(stream); - CFRunLoopRun(); // This will block until the stream is stopped. - FSEventStreamStop(stream); - FSEventStreamInvalidate(stream); - FSEventStreamRelease(stream); CFRelease(pathsToWatch); CFRelease(pathToWatch); + return true; } void stop() { - if (nullptr == runLoop) { + if (nullptr == stream) { return; } - if (CFRunLoopIsWaiting(runLoop) == 0U) { - CFRunLoopWakeUp(runLoop); - } - CFRunLoopStop(runLoop); + FSEventStreamStop(stream); + FSEventStreamInvalidate(stream); + FSEventStreamRelease(stream); } - void run() { monitor(); } + bool run() { return monitor(); } MonitorDir *q_ptr; - CFRunLoopRef runLoop = nullptr; + FSEventStreamRef stream = nullptr; std::filesystem::path dir; - std::thread monitorThread; }; MonitorDir::MonitorDir(const std::filesystem::path &dir) @@ -179,29 +187,20 @@ MonitorDir::~MonitorDir() bool MonitorDir::start() { - if (m_isRunning) { + if (m_isRunning.load()) { std::cerr << "MonitorDir is already running" << std::endl; return false; } - - m_isRunning.store(true); - d_ptr->monitorThread = std::thread([this] { - d_ptr->run(); - m_isRunning.store(false); - }); - - return true; + m_isRunning.store(d_ptr->run()); + return m_isRunning.load(); } void MonitorDir::stop() { - if (!m_isRunning) { + if (!m_isRunning.load()) { std::cerr << "MonitorDir is not running" << std::endl; return; } d_ptr->stop(); - if (d_ptr->monitorThread.joinable()) { - d_ptr->monitorThread.join(); - } } From 77c7acc99c9b504cbb2fe46357a4568b0da3a00f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=AE=E7=94=9F=E8=8B=A5=E6=A2=A6?= <1070753498@qq.com> Date: Wed, 10 Sep 2025 14:43:35 +0800 Subject: [PATCH 3/4] =?UTF-8?q?[=E4=BE=9D=E8=B5=96=E5=92=8C=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E6=9B=B4=E6=96=B0]:=20=E5=8D=87=E7=BA=A7GitH?= =?UTF-8?q?ub=20Actions=E5=92=8Cvcpkg=E4=BE=9D=E8=B5=96=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GitHub Actions: 将actions/checkout从v4升级到v5版本 - GitHub Actions: 将actions/setup-node从v4升级到v5版本 - GitHub Actions: 在codeql和cpp_linter工作流中忽略dependabot分支 - vcpkg: 调整依赖项顺序并更新baseline至b1b1930 - vcpkg: 移除openssl的单独配置项,合并到curl特性配置中 --- .github/workflows/build.yml | 2 +- .github/workflows/clean_cache.yml | 2 +- .github/workflows/codeql.yml | 9 +++++++-- .github/workflows/cpp_linter.yml | 6 +++++- .github/workflows/readme.yml | 4 ++-- vcpkg.json | 14 +++++++------- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 888f13f..5f0e68b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: - "Ninja" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 1 diff --git a/.github/workflows/clean_cache.yml b/.github/workflows/clean_cache.yml index 921d546..3db95d4 100644 --- a/.github/workflows/clean_cache.yml +++ b/.github/workflows/clean_cache.yml @@ -12,7 +12,7 @@ jobs: contents: read steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Cleanup run: | diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 02e07bf..078c478 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -7,13 +7,18 @@ on: - '.gitignore' - 'LICENSE' - 'README*' + branches-ignore: + - 'dependabot/**' + pull_request: paths-ignore: - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' - + branches-ignore: + - 'dependabot/**' + schedule: - cron: '0 0 1 * *' workflow_dispatch: @@ -24,7 +29,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 1 diff --git a/.github/workflows/cpp_linter.yml b/.github/workflows/cpp_linter.yml index 5a1b989..be4a27d 100644 --- a/.github/workflows/cpp_linter.yml +++ b/.github/workflows/cpp_linter.yml @@ -7,18 +7,22 @@ on: - '.gitignore' - 'LICENSE' - 'README*' + branches-ignore: + - 'dependabot/**' pull_request: paths-ignore: - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' + branches-ignore: + - 'dependabot/**' jobs: cpp-linter: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 1 diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml index ebe25e0..23e39e9 100644 --- a/.github/workflows/readme.yml +++ b/.github/workflows/readme.yml @@ -12,9 +12,9 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 # ISO Langusge Codes: https://cloud.google.com/translate/docs/languages - name: Adding README - English uses: dephraiim/translate-readme@main diff --git a/vcpkg.json b/vcpkg.json index 57a54e8..e098d67 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -10,12 +10,6 @@ "efsw", "glog", "gtest", - { - "name": "openssl", - "features": [ - "tools" - ] - }, { "name": "curl", "features": [ @@ -25,7 +19,13 @@ "http2", "tool" ] + }, + { + "name": "openssl", + "features": [ + "tools" + ] } ], - "builtin-baseline": "d8ad13c401b30c2836d00b8923c9127f05f591c7" + "builtin-baseline": "b1b19307e2d2ec1eefbdb7ea069de7d4bcd31f01" } From 565bd7175247b7ce75600bdfd43b0603ee540d65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Oct 2025 11:16:16 +0000 Subject: [PATCH 4/4] Bump actions/setup-node from 5 to 6 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5 to 6. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/readme.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml index 23e39e9..3fce643 100644 --- a/.github/workflows/readme.yml +++ b/.github/workflows/readme.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 # ISO Langusge Codes: https://cloud.google.com/translate/docs/languages - name: Adding README - English uses: dephraiim/translate-readme@main