Skip to content
  • Limiting a number of processes/instances

    Unsolved C++ Gurus limit processes
    5
    0 Votes
    5 Posts
    2k Views
    kshegunovK
    You could try something along these lines: #include <QThread> #include <QSystemSemaphore> #include <QSemaphore> class ProcessCounter { class ProcessCounterThread : public QThread { public: ProcessCounterThread(qint64 timeout, QSystemSemaphore &); void release(); void cancel(); bool success() const; protected: void run() override; private: bool acquired; qint64 maxWaitTime; QSemaphore semaphore; QSystemSemaphore & systemSemaphore; }; public: ProcessCounter(const QString & key, int count, qint64 timeout = 1000); ~ProcessCounter(); bool acquired() const; private: QSystemSemaphore semaphore; ProcessCounterThread thread; }; inline ProcessCounter::ProcessCounterThread::ProcessCounterThread(qint64 timeout, QSystemSemaphore & sem) : acquired(false), maxWaitTime(timeout), systemSemaphore(sem) { } inline bool ProcessCounter::ProcessCounterThread::success() const { return acquired; } inline void ProcessCounter::ProcessCounterThread::release() { semaphore.release(); } inline void ProcessCounter::ProcessCounterThread::cancel() { semaphore.release(); wait(); acquired = false; } void ProcessCounter::ProcessCounterThread::run() { acquired = semaphore.tryAcquire(1, maxWaitTime); if (!acquired) systemSemaphore.release(); } ProcessCounter::ProcessCounter(const QString & key, int count, qint64 timeout) : semaphore(key, count), thread(timeout, semaphore) { thread.start(); if (!semaphore.acquire()) { thread.cancel(); // ... Error handling return; } thread.wait(); // Wait a bit hoping for the global resource to become available } ProcessCounter::~ProcessCounter() { if (thread.success()) semaphore.release(); // We had our global semaphore acquired, now it's time to release it } inline bool ProcessCounter::acquired() const { return thread.success(); } Usage on the stack (as expected): static const int maxProcesses = 20; static const qint64 timeout = 1000; static const QString key = QStringLiteral("KeyForTheGlobalSemaphore"); int main(int argc, char ** argv) { QApplication app(argc, argv); ProcessCounter counter(key, maxProcesses, timeout); if (!counter.acquired()) return 0; // Not allowed, too many processes running already return QApplication::exec(); } Note you'd need to handle SIGSEGV and possibly other signals manually and you shouldn't call ::exit at all, because it will not run the ProcessCounter's destructor, meaning the global semaphore won't be released. Graceful shutdown is paramount here.