|
- /*
- * Carla common utils
- * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a full copy of the GNU General Public License see the GPL.txt file
- */
-
- #ifndef __CARLA_THREAD_HPP__
- #define __CARLA_THREAD_HPP__
-
- #include "CarlaJuceUtils.hpp"
-
- // #define CPP11_THREAD
-
- #ifdef CPP11_THREAD
- # include <thread>
- #else
- # include <pthread.h>
- #endif
-
- // -------------------------------------------------
- // CarlaThread class
-
- class CarlaThread
- {
- public:
- CarlaThread()
- : fStarted(false),
- fFinished(false)
- {
- #ifdef CPP11_THREAD
- cthread = nullptr;
- #else
- _zero();
- pthread_attr_init(&pthreadAttr);
- pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE);
- #endif
- }
-
- ~CarlaThread()
- {
- CARLA_ASSERT(! isRunning());
-
- if (isRunning())
- terminate();
-
- #ifdef CPP11_THREAD
- if (cthread != nullptr)
- {
- cthread->join();
- delete cthread;
- }
- #else
- if (! _isNull())
- pthread_join(pthreadId, nullptr);
-
- pthread_attr_destroy(&pthreadAttr);
- #endif
- }
-
- bool start()
- {
- CARLA_ASSERT(! isRunning());
-
- if (isRunning())
- return false;
-
- fStarted = false;
- fFinished = false;
-
- #ifdef CPP11_THREAD
- CARLA_ASSERT(cthread == nullptr);
-
- if (cthread != nullptr)
- return false;
-
- cthread = new std::thread(_cthreadRoutine, this);
- CARLA_ASSERT(cthread->joinable());
-
- return true;
- #else
- CARLA_ASSERT(_isNull());
-
- if (! _isNull())
- return false;
-
- return (pthread_create(&pthreadId, &pthreadAttr, _pthreadRoutine, this) == 0);
- #endif
- }
-
- bool stop(const unsigned int timeout = 0)
- {
- CARLA_ASSERT(isRunning());
-
- if (! isRunning())
- return true;
-
- #ifdef CPP11_THREAD
- if (cthread == nullptr)
- return true;
- #else
- if (_isNull())
- return true;
- #endif
-
- if (timeout == 0)
- {
- #ifdef CPP11_THREAD
- cthread->join();
- #else
- pthread_join(pthreadId, nullptr);
- #endif
- }
- else
- {
- for (unsigned int i=0; i < timeout && ! fFinished; i++)
- carla_msleep(1);
- }
-
- if (! fFinished)
- return false;
-
- #ifdef CPP11_THREAD
- delete cthread;
- cthread = nullptr;
- #else
- _zero();
- #endif
-
- return true;
- }
-
- void terminate()
- {
- CARLA_ASSERT(isRunning());
-
- if (fFinished)
- return;
-
- #ifdef CPP11_THREAD
- if (cthread == nullptr)
- return;
- #else
- if (_isNull())
- return;
- #endif
-
- #ifdef CPP11_THREAD
- cthread->detach();
- //cthread->join();
- delete cthread;
- cthread = nullptr;
- #else
- pthread_detach(pthreadId);
- //pthread_join(pthreadId, nullptr);
- pthread_cancel(pthreadId);
- _zero();
- #endif
-
- fFinished = true;
- }
-
- bool isRunning()
- {
- if (fStarted && ! fFinished)
- return true;
-
- // take the change to clear data
- #ifdef CPP11_THREAD
- if (cthread != nullptr)
- {
- cthread->join();
- delete cthread;
- cthread = nullptr;
- }
- #else
- if (! _isNull())
- {
- pthread_join(pthreadId, nullptr);
- _zero();
- }
- #endif
- return false;
- }
-
- void waitForStarted(const unsigned int timeout = 0) // ms
- {
- if (fStarted)
- return;
-
- if (timeout == 0)
- {
- while (! fStarted) {}
- }
- else
- {
- for (unsigned int i=0; i < timeout && ! fStarted; i++)
- carla_msleep(1);
- }
- }
-
- void waitForFinished()
- {
- waitForStarted();
- stop(0);
- }
-
- protected:
- virtual void run() = 0;
-
- private:
- bool fStarted;
- bool fFinished;
-
- void handleRoutine()
- {
- fStarted = true;
- run();
- fFinished = true;
- }
-
- #ifdef CPP11_THREAD
- std::thread* cthread;
-
- static void _cthreadRoutine(CarlaThread* const _this_)
- {
- _this_->handleRoutine();
- }
- #else
- pthread_t pthreadId;
- pthread_attr_t pthreadAttr;
-
- static void* _pthreadRoutine(void* const _this_)
- {
- ((CarlaThread*)_this_)->handleRoutine();
- pthread_exit(nullptr);
- return nullptr;
- }
-
- bool _isNull()
- {
- #ifdef CARLA_OS_WIN
- return (pthreadId.p == nullptr);
- #else
- return (pthreadId == 0);
- #endif
- }
-
- void _zero()
- {
- carla_zeroStruct<pthread_t>(pthreadId);
- }
- #endif
-
- CARLA_PREVENT_HEAP_ALLOCATION
- CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread)
- };
-
- // -------------------------------------------------
-
- #endif // __CARLA_THREAD_HPP__
|