Существует множество примеров, позволяющих запускать только один экземпляр программы. Но мне нужно, чтобы мне нужно было запускать «N» (например, N = 5) экземпляров приложения, но не превышать его. Я не смог найти в Интернете никаких ресурсов по этому поводу.
class InstanceMaintainer{
private:
HANDLE h_ = nullptr;
public:
InstanceMaintainer(const std::string& programName, unsigned maxInstances, unsigned& obtainedInstanceId){
const auto semOrMutexName = "Global\\" + programName;
obtainedInstanceId = -1;
for (unsigned i = 0; i < maxInstances; i++){
auto mutexName = semOrMutexName + std::to_string(i);
h_ = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, mutexName.c_str());
if (h_ != nullptr){
const auto dwWaitResult = WaitForSingleObject(h_, 0L);
if (dwWaitResult == WAIT_TIMEOUT){
CloseHandle(h_);
h_ = nullptr;
}else{
obtainedInstanceId = i;
break;
}
}
else{
if (GetLastError() == ERROR_FILE_NOT_FOUND){
h_ = CreateMutexA(nullptr, TRUE, mutexName.c_str());
if (h_ == nullptr){
const auto err = "CreateMutex failed with " + std::to_string(GetLastError());
throw std::exception(err.c_str());
}else{
obtainedInstanceId = i;
break;
}
}else{
const auto err = "OpenMutex failed with " + std::to_string(GetLastError());
throw std::exception(err.c_str());
}
}
}
if (obtainedInstanceId == unsigned(-1)){
throw std::exception("All instances are already taken\n");
}
}
~InstanceMaintainer(){
ReleaseMutex(h_);
CloseHandle(h_);
}
};
int main(){
try{
unsigned instanceId = -1;
InstanceMaintainer im("Quickie", 7, instanceId);
std::cout << "Running " << instanceId << "\n";
}catch (std::exception& e){
std::cout << e.what() << "\n";
}
return 0;
}
Это то, что я придумал. Это windows конкретный c. Есть ли c ++ стандартный способ сделать это? Как обходится отсутствие именованного мьютекса в std :: mutex? Я знаю, что есть названный семафор в c ++ posix. Но он не может вернуть идентификатор экземпляра, что, в свою очередь, будет полезно для доступа к ресурсам.