Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LockFreeCallbackDispatcher.hpp 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* Copyright 2016, Ableton AG, Berlin. All rights reserved.
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * If you would like to incorporate Link into a proprietary software application,
  17. * please contact <link-devs@ableton.com>.
  18. */
  19. #pragma once
  20. #include <atomic>
  21. #include <condition_variable>
  22. #include <thread>
  23. namespace ableton
  24. {
  25. namespace platforms
  26. {
  27. // Utility to signal invocation of a callback on another thread in a lock free manner.
  28. // The callback is evoked on a thread owned by the instance of this class.
  29. //
  30. // A condition variable is used to notify a waiting thread, but only if the required
  31. // lock can be acquired immediately. If that fails, we fall back on signaling
  32. // after a timeout. This gives us a guaranteed minimum signalling rate which is defined
  33. // by the fallbackPeriod parameter.
  34. template <typename Callback, typename Duration>
  35. class LockFreeCallbackDispatcher
  36. {
  37. public:
  38. LockFreeCallbackDispatcher(Callback callback, Duration fallbackPeriod)
  39. : mCallback(std::move(callback))
  40. , mFallbackPeriod(std::move(fallbackPeriod))
  41. , mRunning(true)
  42. , mThread([this] { run(); })
  43. {
  44. }
  45. ~LockFreeCallbackDispatcher()
  46. {
  47. mRunning = false;
  48. mCondition.notify_one();
  49. mThread.join();
  50. }
  51. void invoke()
  52. {
  53. if (mMutex.try_lock())
  54. {
  55. mCondition.notify_one();
  56. mMutex.unlock();
  57. }
  58. }
  59. private:
  60. void run()
  61. {
  62. while (mRunning.load())
  63. {
  64. {
  65. std::unique_lock<std::mutex> lock(mMutex);
  66. mCondition.wait_for(lock, mFallbackPeriod);
  67. }
  68. mCallback();
  69. }
  70. }
  71. Callback mCallback;
  72. Duration mFallbackPeriod;
  73. std::atomic<bool> mRunning;
  74. std::mutex mMutex;
  75. std::condition_variable mCondition;
  76. std::thread mThread;
  77. };
  78. } // namespace platforms
  79. } // namespace ableton