반응형
client의 요청이 많을 때 동시접근 및 부하를 해결하기 위한 방안...
- 작업 중이면, 캐시 떠 놓은거 사용. 즉, 빠른 응답이 가능하도록.
- read lock, write lock 으로 구분. read 작업은 동시 접근 가능.
#include <iostream>
#include <vector>
#include <shared_mutex>
#include <optional>
#include <thread>
#include <chrono>
#include <atomic>
#include <string>
#include <windows.h>
#include <tlhelp32.h>
// 가정: PROCESS_INFO 구조체
struct PROCESS_INFO {
int pid;
std::string name;
};
std::vector<PROCESS_INFO> g_process; // 프로세스 목록
std::optional<std::vector<PROCESS_INFO>> g_process_cache; // 캐시된 프로세스 목록
std::shared_mutex process_mutex; // 동기화 도구
std::atomic<bool> is_updating{false}; // 업데이트 중인지 확인하는 플래그 추가
// 프로세스 목록을 갱신하는 함수
void update_process(int id) {
if (is_updating.exchange(true)) {
std::cout << "Update already in progress, skipping. : thread id=" << id << "\n";
return;
}
std::cout << "Update processing. : thread id=" << id << "\n";
std::vector<PROCESS_INFO> updated_process;
// 프로세스 스냅샷 생성
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot != INVALID_HANDLE_VALUE) {
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(pe32);
// 첫번째 프로세스 정보 가져오기
if (Process32FirstW(snapshot, &pe32)) {
do {
// 와이드 문자열을 일반 문자열로 변환
std::wstring wname(pe32.szExeFile);
std::string name(wname.begin(), wname.end());
// 프로세스 정보 추가
updated_process.push_back({
static_cast<int>(pe32.th32ProcessID),
name
});
} while (Process32NextW(snapshot, &pe32));
}
CloseHandle(snapshot);
}
// 실제 데이터 업데이트
{
std::unique_lock<std::shared_mutex> lock(process_mutex);
g_process = std::move(updated_process);
}
is_updating = false;
}
// 프로세스 목록을 출력하는 함수
void print_process(int id) {
std::shared_lock<std::shared_mutex> lock(process_mutex);
if (!g_process_cache || g_process_cache->size() != g_process.size()) {
// 캐시가 없거나 크기가 다르면 캐시 업데이트
g_process_cache = g_process;
}
lock.unlock(); // 캐시를 읽을 때는 잠금 해제
// 캐시된 데이터 사용
const auto& process_list = g_process_cache.value();
std::cout << "Current Process List: thread id=" << id << "\n";
for (const auto& proc : process_list) {
// std::cout << "PID: " << proc.pid << ", Name: " << proc.name << "\n";
}
std::cout << "Current Process Count : " << process_list.size() << " thread id=" << id << "\n";
}
// 클라이언트 스레드
void client_thread(int id) {
std::cout << "Client " << id << " started.\n";
for (int i=0; i<10; i++ ) {
update_process(id); // 프로세스 정보 갱신
print_process(id); // 최신 프로세스 정보 출력
std::this_thread::sleep_for(std::chrono::milliseconds(rand()%100));
}
std::cout << "Client " << id << " finished.\n";
}
int main() {
update_process(0);
// 여러 스레드에서 동작 시뮬레이션
int thread_count = 10;
std::vector<std::thread> threads;
for(int i=0; i<thread_count; i++) {
threads.push_back(std::thread(client_thread, i+1));
}
for(auto& thread : threads) {
thread.join();
}
return 0;
}
'Develop > C&CPP' 카테고리의 다른 글
[service] 윈도우 서비스 프로그램 (0) | 2025.01.05 |
---|---|
[server] ThreadPool, client 접속이 많을 때. TCP Server (0) | 2025.01.05 |
[알고리즘] 정렬 알고리즘 비교/성능측정 (1) | 2019.12.16 |
[알고리즘] 정렬5: quick sort (0) | 2019.12.15 |
[알고리즘] 정렬4: merge sort (0) | 2019.12.15 |