reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

event.cpp (2058B)


      1 /* ReaPack: Package manager for REAPER
      2  * Copyright (C) 2015-2025  Christian Fillion
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU Lesser General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 #include "event.hpp"
     19 
     20 #include <reaper_plugin_functions.h>
     21 
     22 static std::weak_ptr<AsyncEventImpl::Loop> s_loop;
     23 
     24 AsyncEventImpl::Loop::Loop()
     25 {
     26   plugin_register("timer", reinterpret_cast<void *>(&mainThreadTimer));
     27 }
     28 
     29 AsyncEventImpl::Loop::~Loop()
     30 {
     31   plugin_register("-timer", reinterpret_cast<void *>(&mainThreadTimer));
     32 }
     33 
     34 void AsyncEventImpl::Loop::mainThreadTimer()
     35 {
     36   s_loop.lock()->processQueue();
     37 }
     38 
     39 void AsyncEventImpl::Loop::push(const MainThreadFunc &event, const void *source)
     40 {
     41   std::lock_guard<std::mutex> guard(m_mutex);
     42   m_queue.insert({source, event});
     43 }
     44 
     45 void AsyncEventImpl::Loop::forget(const void *source)
     46 {
     47   std::lock_guard<std::mutex> guard(m_mutex);
     48   m_queue.erase(source);
     49 }
     50 
     51 void AsyncEventImpl::Loop::processQueue()
     52 {
     53   decltype(m_queue) events;
     54 
     55   {
     56     std::lock_guard<std::mutex> guard(m_mutex);
     57     std::swap(events, m_queue);
     58   }
     59 
     60   for(const auto &[emitter, func] : events)
     61     func(), (void)emitter;
     62 }
     63 
     64 AsyncEventImpl::Emitter::Emitter()
     65 {
     66   if(s_loop.expired())
     67     s_loop = m_loop = std::make_shared<Loop>();
     68   else
     69     m_loop = s_loop.lock();
     70 }
     71 
     72 AsyncEventImpl::Emitter::~Emitter()
     73 {
     74   if(s_loop.use_count() > 1)
     75     m_loop->forget(this);
     76 }
     77 
     78 void AsyncEventImpl::Emitter::runInMainThread(const MainThreadFunc &event) const
     79 {
     80   m_loop->push(event, this);
     81 }