Commit 25cee581 authored by Atream's avatar Atream
Browse files

add balance-serve, support concurrence

parent 8d0292aa
#ifndef __MUTEX_EXTEND_HPP_
#define __MUTEX_EXTEND_HPP_
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
class non_recursive_mutex {
public:
non_recursive_mutex() = default;
// 使用 try_lock 实现非递归锁
bool try_lock() {
std::thread::id this_id = std::this_thread::get_id();
// 检查当前线程是否已经持有该锁
if (owner.load(std::memory_order_acquire) == this_id) {
return false; // 如果是当前线程,返回失败
}
// 尝试加锁
if (mtx.try_lock()) {
owner.store(this_id, std::memory_order_release); // 设置锁的拥有者
return true;
}
return false;
}
// lock 会阻塞,直到获得锁
void lock() {
std::thread::id this_id = std::this_thread::get_id();
while (true) {
// 检查当前线程是否已经持有该锁
if (owner.load(std::memory_order_acquire) == this_id) {
throw std::runtime_error("Thread is trying to lock a mutex it already holds");
}
// 尝试加锁
if (mtx.try_lock()) {
owner.store(this_id, std::memory_order_release); // 设置锁的拥有者
return;
}
// 如果锁未获得,则稍微等待,防止忙等
std::this_thread::yield();
}
}
// 解锁
void unlock() {
std::thread::id this_id = std::this_thread::get_id();
// 确保只有持有锁的线程可以解锁
if (owner.load(std::memory_order_acquire) == this_id) {
owner.store(std::thread::id(), std::memory_order_release); // 清除锁的拥有者
mtx.unlock();
} else {
throw std::runtime_error("Thread attempting to unlock a mutex it doesn't own");
}
}
private:
std::mutex mtx; // 实际的互斥量
std::atomic<std::thread::id> owner; // 原子变量,记录当前锁的拥有者
};
#endif
#ifndef PERIODIC_TASK_HPP
#define PERIODIC_TASK_HPP
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstdio>
#include <functional>
#include <future>
#include <iostream>
#include <mutex>
#include <stop_token>
#include <thread>
#include <utility>
#include <vector>
namespace periodic {
class PeriodicTask {
public:
explicit PeriodicTask(std::function<void()> func,
std::chrono::milliseconds interval_ms = std::chrono::milliseconds(100))
: func_(std::move(func)), interval_(interval_ms), worker_([this](std::stop_token stoken) { this->run(stoken); }) {
// std::cout << "PeriodicTask created with interval: " << interval_.count() << " ms" << std::endl;
}
~PeriodicTask() {
worker_.request_stop();
cv_.notify_one(); // Ensure worker wakes up when destroyed
// std::cout << "PeriodicTask destructor called, stopping worker." << std::endl;
}
void wakeUp() {
{
std::lock_guard<std::mutex> lock(wakeup_mutex_);
wake_up_requested_ = true;
}
cv_.notify_one(); // Notify worker thread to wake up immediately
// std::cout << "wakeUp() called: worker thread will wake up." << std::endl;
}
std::future<void> wakeUpWait() {
std::promise<void> promise;
std::future<void> future = promise.get_future();
{
std::lock_guard<std::mutex> lock(promise_mutex_);
wakeup_promises_.push_back(std::move(promise));
}
wakeUp();
return future;
}
private:
void run(std::stop_token stoken) {
while (!stoken.stop_requested()) {
std::unique_lock lock(mutex_);
// Wait for either the time interval or a wake-up signal
cv_.wait_for(lock, interval_, [this] { return wake_up_requested_.load(); });
if (stoken.stop_requested())
break;
// If the wake-up was triggered, reset the flag and process the task
{
std::lock_guard<std::mutex> lock(wakeup_mutex_);
wake_up_requested_ = false;
}
try {
// std::cout << "Running task function." << std::endl;
func_();
} catch (...) {
std::cerr << "Error in task function." << std::endl;
}
notifyPromises();
}
}
void notifyPromises() {
std::lock_guard<std::mutex> lock(promise_mutex_);
// std::cout << "Notifying all waiting promises." << std::endl;
for (auto& promise : wakeup_promises_) {
promise.set_value();
}
wakeup_promises_.clear();
}
std::function<void()> func_;
std::chrono::milliseconds interval_;
std::mutex mutex_;
std::condition_variable cv_;
std::vector<std::promise<void>> wakeup_promises_;
std::mutex promise_mutex_;
std::mutex wakeup_mutex_;
std::atomic<bool> wake_up_requested_ = false;
std::jthread worker_;
};
} // namespace periodic
#endif // PERIODIC_TASK_HPP
/*
* @Author: Xie Weiyu ervinxie@qq.com
* @Date: 2024-11-21 06:35:47
* @LastEditors: Xie Weiyu ervinxie@qq.com
* @LastEditTime: 2024-11-21 06:35:50
* @FilePath: /kvc2/src/utils/spin_lock.hpp
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置:
* https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include <atomic>
#include <chrono>
#include <thread>
class SpinLock {
public:
SpinLock() { flag.clear(); }
void lock() {
const int max_delay = 1024; // Maximum delay in microseconds
int delay = 1; // Initial delay in microseconds
while (flag.test_and_set(std::memory_order_acquire)) {
std::this_thread::sleep_for(std::chrono::microseconds(delay));
delay *= 2;
if (delay > max_delay) {
delay = max_delay;
}
}
}
void unlock() { flag.clear(std::memory_order_release); }
private:
std::atomic_flag flag = ATOMIC_FLAG_INIT;
};
#pragma once
#include <cassert>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include "easy_format.hpp"
inline std::string doubleToStringR2(double value) {
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << value;
return stream.str();
}
class Timer {
public:
std::string name;
bool tmp_timer = false;
Timer() {}
Timer(std::string name) : name(name), tmp_timer(true) { start(); }
~Timer() {
if (tmp_timer) {
std::cout << name << " " << elapsedMs() << " ms" << std::endl;
}
}
void start() {
m_startTime = std::chrono::high_resolution_clock::now();
assert(m_isRunning == false);
m_isRunning = true;
}
void stop() {
m_endTime = std::chrono::high_resolution_clock::now();
assert(m_isRunning == true);
m_isRunning = false;
m_runningNs += elapsedNs();
}
double elapsedNs() {
std::chrono::time_point<std::chrono::high_resolution_clock> endTime;
if (m_isRunning) {
endTime = std::chrono::high_resolution_clock::now();
} else {
endTime = m_endTime;
}
return std::chrono::duration_cast<std::chrono::nanoseconds>(endTime - m_startTime).count();
}
void printElapsedMilliseconds() { std::cout << elapsedNs() / 1e6 << " ms" << std::endl; }
static std::string ns_to_string(double duration) {
auto nano_sec = duration;
if (nano_sec >= 1000) {
auto mirco_sec = nano_sec / 1000.0;
if (mirco_sec >= 1000) {
auto milli_sec = mirco_sec / 1000.0;
if (milli_sec >= 1000) {
auto seconds = milli_sec / 1000.0;
if (seconds >= 60.0) {
auto minutes = seconds / 60.0;
if (minutes >= 60.0) {
auto hours = minutes / 60.0;
return doubleToStringR2(hours) + " h";
} else {
return doubleToStringR2(minutes) + " min";
}
} else {
return doubleToStringR2(seconds) + " sec";
}
} else {
return doubleToStringR2(milli_sec) + " ms";
}
} else {
return doubleToStringR2(mirco_sec) + " us";
}
} else {
return doubleToStringR2(nano_sec) + " ns";
}
}
double runningTimeNs() { return m_runningNs; }
std::string runningTime() {
auto duration = m_runningNs;
return ns_to_string(duration);
}
std::string elapsedTime() { return ns_to_string(elapsedNs()); }
double elapsedMs() { return elapsedNs() / 1e6; }
std::string report_throughput(size_t op_cnt) {
double ops = op_cnt / elapsedMs() * 1000;
return readable_number(ops) + "op/s";
}
void merge(Timer& other) {
assert(m_isRunning == false);
assert(other.m_isRunning == false);
m_runningNs += other.runningTimeNs();
}
private:
std::chrono::time_point<std::chrono::high_resolution_clock> m_startTime;
std::chrono::time_point<std::chrono::high_resolution_clock> m_endTime;
bool m_isRunning = false;
double m_runningNs = 0.0;
};
class Counter {
public:
Counter() {}
std::map<std::string, size_t> counters;
void inc(const char* name, size_t num) { counters[name] += num; };
void print() {
for (auto& p : counters) {
std::cout << p.first << " : " << p.second << std::endl;
}
};
};
This diff is collapsed.
#include <tbb/concurrent_hash_map.h>
#include <iostream>
int main() {
tbb::concurrent_hash_map<int, int> map;
map.insert({1, 2});
decltype(map)::accessor a;
std::cout << map.find(a, 1) << std::endl;
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment