Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- "Ninja"

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 1

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/clean_cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
contents: read
steps:
- name: Check out code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Cleanup
run: |
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -24,7 +29,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 1

Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/cpp_linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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@v6
# ISO Langusge Codes: https://cloud.google.com/translate/docs/languages
- name: Adding README - English
uses: dephraiim/translate-readme@main
Expand Down
139 changes: 69 additions & 70 deletions MonitorDir/monitordir_mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,83 +3,90 @@
#include <CoreServices/CoreServices.h>

#include <iostream>
#include <thread>

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
Expand All @@ -101,7 +108,7 @@ class MonitorDir::MonitorDirPrivate
// auto *monitorDir = static_cast<MonitorDirPrivate *>(clientCallBackInfo);
char **paths = static_cast<char **>(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) {
Expand All @@ -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<const void **>(&pathToWatch),
1,
nullptr);
std::cout << "addWatch" << dir << std::endl;
auto pathToWatch = CFStringCreateWithCString(kCFAllocatorDefault,
dir.c_str(),
kCFStringEncodingUTF8);
auto pathsToWatch = CFArrayCreate(kCFAllocatorDefault,
reinterpret_cast<const void **>(&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)
Expand All @@ -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();
}
}
56 changes: 56 additions & 0 deletions README.en.md
Original file line number Diff line number Diff line change
@@ -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;
Loading