- C 95.4%
- C++ 4.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| src | ||
| .gitignore | ||
| nob.c | ||
| nob.h | ||
| readme.org | ||
Cpp-template
This is mostly repository for a fancy Makefile that handles project setup for you. Also as an added feature, shows the actual error messages on the end of the compile message.
MADE MOSTLY FOR MYSELF!
The mio.h is split on "modules" to avoid pulling in a lot of std headers when you only need one part of the library.
Example usage
mio.h is an stb-style C++ single header library. Include it wherever you need it,
and in exactly one .cpp define MIO_IMPLEMENTATION first to compile the implementation.
Options like MIO_MULTITHREAD must be defined before every include.
#define MIO_MULTITHREAD
#define MIO_IMPLEMENTATION
#include "mio.h"
String manipulation
Mio provides two types of trimming functions
- trim_sv
- returns a trimmed string_view. Doesnt touch the original
- trim_str
- Trims string in place
std::string_view sv = " Meow ";
sv = mio::trim_sv(sv);
std::println("{}", sv);
std::string str = " Meow ";
mio::trim_str(str);
std::println("{}", str);
File operations
-
Functions:
- write_entire_file
- Writes a string into a file
-
Enums:
- writeMode
-
Enum to use for write mode
- writeMode::write
- writeMode::append
mio::write_entire_file("test.txt", std::string("some data\n"), mio::writeMode::write);
Channels/Multithreading
mio.h provides bounded channels (needs MIO_MULTITHREAD), example:
std::atomic<int> done {0};
void work(int id, std::string& out) {
std::string str = "Hello from thread " + std::to_string(id) + "\n";
std::lock_guard lk(mutex);
out += str;
}
auto main() -> int {
Channel<int> ch(16);
std::vector<std::jthread> workers;
// make 4 workers
for (int i = 0; i < 4; i++) {
workers.emplace_back([&] {
// grab jobs from the channel on each worker and increment atomic counter.
while (auto job = ch.recv()) {
work(*job, std::ref(s));
done.fetch_add(1, std::memory_order_relaxed);
}
});
}
// Send 100 jobs to the channel
for (int i = 0; i < 100; i++) ch.send(i);
// Close the channel and await the workers
ch.close();
workers.clear();
std::println("Jobs done: {}", done.load());
return 0;
}
Simple single producer single consumer: (The library is not optimized for this, it uses the same mechanism as the multiple consumers)
Channel<int> ch(16);
// Start a single thread consumer
std::jthread consumer([&] {
// Lambda captures everything by reference
while (auto v = ch.recv()) {
std::println("got {}", *v);
}
});
// Send 10 messages to the Channel.
for (int i = 0; i < 10; i++) {
ch.send(i);
}
// Close the channel.
ch.close();
// awaits before continuing
consumer.join();
Just a simple mutex example bc my memory is of a goldfish:
std::mutex mutex
void work(int id, std::string& out) {
std::string str = "Hello from thread " + std::to_string(id) + "\n";
// Create a new lock and lock using our mutex instance
std::lock_guard lk(mutex);
out += str;
// unlock the mutex automatically in the scope end
}
auto main() -> void {
std::string s;
std::thread t;
std::thread t2;
t = std::thread(work, 1, std::ref(s));
t2 = std::thread(work, 2, std::ref(s));
t.join();
t2.join();
std::println("{}", s);
}
Shell run
mio.h provides shell run helper (needs MIO_SHELL), example:
// Takes in a vector of strings
// Could do: std::vector<std::string> cmds = {"ffmpeg", "-version"};
// auto cmd = mio::run(cmds);
auto cmd = mio::run({"ffmpeg", "-version"});
std::println("Output: {}, code: {}", cmd.out, cmd.code);
doctest
This template also sets up tests inside src/tests, follow the tests.cpp example and continue it. To run the tests:
make test
Nob
This template uses nob.h (nobuild made by Rexim) for building the project. The whole build script is defined in "nob.c". All the targets builds inside build/MODENAME/
# Bootstrap nob once
cc -o nob nob.c
# debug build
./nob
# release build
./nob release
# run doctest from "src/tests/tests.cpp"
./nob test