|
libpsynth 0.2.1
|
00001 00011 /* 00012 * Copyright (C) 2011 Juan Pedro BolĂvar Puente 00013 * 00014 * This file is part of Psychosynth. 00015 * 00016 * Psychosynth is free software: you can redistribute it and/or modify 00017 * it under the terms of the GNU General Public License as published by 00018 * the Free Software Foundation, either version 3 of the License, or 00019 * (at your option) any later version. 00020 * 00021 * Psychosynth is distributed in the hope that it will be useful, 00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00024 * GNU General Public License for more details. 00025 * 00026 * You should have received a copy of the GNU General Public License 00027 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00028 * 00029 */ 00030 00031 #ifndef PSYNTH_GRAPH_PROCESSOR_HPP_ 00032 #define PSYNTH_GRAPH_PROCESSOR_HPP_ 00033 00034 #include <thread> 00035 #include <atomic> 00036 #include <list> 00037 00038 #include <psynth/new_graph/core/patch_fwd.hpp> 00039 #include <psynth/new_graph/node_fwd.hpp> 00040 #include <psynth/new_graph/port_fwd.hpp> 00041 #include <psynth/new_graph/sink_node_fwd.hpp> 00042 #include <psynth/new_graph/process_node_fwd.hpp> 00043 00044 #include <psynth/new_graph/exception.hpp> 00045 #include <psynth/new_graph/event.hpp> 00046 #include <psynth/new_graph/triple_buffer.hpp> 00047 00048 #include <psynth/base/hetero_deque.hpp> 00049 #include <psynth/base/threads.hpp> 00050 00051 namespace psynth 00052 { 00053 namespace graph 00054 { 00055 00056 PSYNTH_DECLARE_ERROR (error, processor_error); 00057 PSYNTH_DECLARE_ERROR (processor_error, processor_not_running_error); 00058 PSYNTH_DECLARE_ERROR (processor_error, processor_not_idle_error); 00059 00060 constexpr std::size_t default_queue_size = 1 << 20; 00061 constexpr std::size_t default_block_size = 1 << 6; 00062 constexpr std::size_t default_frame_rate = 44100; 00063 00064 class processor; 00065 00066 typedef base::hetero_deque<rt_event> rt_event_deque; 00067 typedef base::hetero_deque<async_event> async_event_deque; 00068 00069 typedef triple_buffer< 00070 rt_event_deque, 00071 base::try_lock_guard<>, 00072 base::no_lock_guard<> > 00073 rt_triple_buffer; 00074 00075 typedef triple_buffer< 00076 async_event_deque, 00077 base::no_lock_guard<>, // We handle locking ourselves in the 00078 // processor class because it is not so simple. 00079 base::lock_guard<> > 00080 async_triple_buffer; 00081 00082 class basic_process_context : private boost::noncopyable 00083 { 00084 public: 00085 std::size_t block_size () const 00086 { return _block_size; } 00087 00088 std::size_t frame_rate () const 00089 { return _frame_rate; } 00090 00091 protected: 00093 basic_process_context (std::size_t block_size, 00094 std::size_t frame_rate, 00095 std::size_t queue_size); 00096 00097 rt_triple_buffer _rt_buffers; 00098 async_triple_buffer _async_buffers; 00099 00100 std::size_t _block_size; 00101 std::size_t _frame_rate; 00102 00103 // FIXME: Factor the related functions a bit 00104 std::thread _async_thread; 00105 std::condition_variable _async_cond; 00106 std::mutex _async_mutex; 00107 bool _async_request_flip; 00108 00109 friend class processor; 00110 }; 00111 00112 class rt_process_context : public virtual basic_process_context 00113 { 00114 public: 00115 template <class Event, typename... Args> 00116 bool push_rt_event (Args&&... args); 00117 00118 template <class Event, typename... Args> 00119 bool push_async_event (Args&&... args); 00120 00121 template <class Concrete> 00122 bool push_rt_event (Concrete&& arg) 00123 { 00124 return this->push_rt_event< 00125 typename std::decay<Concrete>::type, 00126 decltype (std::forward<Concrete> (arg))> ( 00127 std::forward<Concrete> (arg)); 00128 } 00129 00130 template <class Concrete> 00131 bool push_async_event (Concrete&& arg) 00132 { 00133 return this->push_async_event< 00134 typename std::decay<Concrete>::type, 00135 decltype (std::forward<Concrete> (arg))> ( 00136 std::forward<Concrete> (arg)); 00137 } 00138 00139 protected: 00140 friend class processor; 00141 00142 rt_process_context (std::size_t block_size, 00143 std::size_t frame_rate, 00144 std::size_t queue_size) 00145 : basic_process_context (block_size, frame_rate, queue_size) 00146 {} 00147 00148 node_ptr _curr_node; 00149 node_ptr _request_node; 00150 out_port_base* _request_output; 00151 }; 00152 00153 class async_process_context : public virtual basic_process_context 00154 { 00155 public: 00156 template <class Event, typename... Args> 00157 bool push_rt_event (Args&&... args); 00158 00159 template <class Event, typename... Args> 00160 bool push_async_event (Args&&... args); 00161 00162 template <class Concrete> 00163 bool push_rt_event (Concrete&& arg) 00164 { 00165 return this->push_rt_event< 00166 typename std::decay<Concrete>::type, 00167 decltype (std::forward<Concrete> (arg))> ( 00168 std::forward<Concrete> (arg)); 00169 } 00170 00171 template <class Concrete> 00172 bool push_async_event (Concrete&& arg) 00173 { 00174 return this->push_async_event< 00175 typename std::decay<Concrete>::type, 00176 decltype (std::forward<Concrete> (arg))> ( 00177 std::forward<Concrete> (arg)); 00178 } 00179 00180 protected: 00181 friend class processor; 00182 00183 async_process_context (std::size_t block_size, 00184 std::size_t frame_rate, 00185 std::size_t queue_size) 00186 : basic_process_context (block_size, frame_rate, queue_size) {} 00187 00188 }; 00189 00190 class user_process_context : public virtual basic_process_context 00191 { 00192 public: 00193 template <class Event, typename... Args> 00194 bool push_rt_event (Args&&... args); 00195 00196 template <class Event, typename... Args> 00197 bool push_async_event (Args&&... args); 00198 00199 template <class Concrete> 00200 bool push_rt_event (Concrete&& arg) 00201 { 00202 return this->push_rt_event< 00203 typename std::decay<Concrete>::type, 00204 decltype (std::forward<Concrete> (arg))> ( 00205 std::forward<Concrete> (arg)); 00206 } 00207 00208 template <class Concrete> 00209 bool push_async_event (Concrete&& arg) 00210 { 00211 return this->push_async_event< 00212 typename std::decay<Concrete>::type, 00213 decltype (std::forward<Concrete> (arg))> ( 00214 std::forward<Concrete> (arg)); 00215 } 00216 00217 protected: 00218 friend class processor; 00219 00220 user_process_context (std::size_t block_size, 00221 std::size_t frame_rate, 00222 std::size_t queue_size) 00223 : basic_process_context (block_size, frame_rate, queue_size) {} 00224 }; 00225 00226 class full_process_context : public rt_process_context 00227 , public async_process_context 00228 , public user_process_context 00229 { 00230 // private: 00231 public: // Eases unit testing! 00232 friend class processor; 00233 00234 full_process_context (std::size_t block_size = 1 << 6, 00235 std::size_t frame_rate = 44100, 00236 std::size_t queue_size = 1 << 10) 00237 : basic_process_context (block_size, frame_rate, queue_size) 00238 , rt_process_context (block_size, frame_rate, queue_size) 00239 , async_process_context (block_size, frame_rate, queue_size) 00240 , user_process_context (block_size, frame_rate, queue_size) 00241 {} 00242 }; 00243 00244 00245 class processor : private boost::noncopyable 00246 { 00247 public: 00248 processor (core::patch_ptr root = 0, 00249 std::size_t block_size = default_block_size, 00250 std::size_t frame_rate = default_frame_rate, 00251 std::size_t queue_size = default_queue_size); 00252 00253 ~processor (); 00254 00255 void start (); 00256 void stop (); 00257 00258 core::patch_ptr root () 00259 { return _root; } 00260 00261 user_process_context& context () 00262 { return _ctx; } 00263 00264 const user_process_context& context () const 00265 { return _ctx; } 00266 00267 void set_block_size (std::size_t new_size); 00268 void set_frame_rate (std::size_t new_frame_rate); 00269 00270 void rt_request_process (std::ptrdiff_t iterations); 00271 void rt_request_process (); 00272 00273 bool is_running () const 00274 { return _is_running; } 00275 00277 void notify_add_node (node_ptr node) 00278 { _explore_node_add (node); } 00279 00281 void notify_remove_node (node_ptr node) 00282 { _explore_node_remove (node); } 00283 00284 private: 00285 void _explore_node_add (node_ptr node); 00286 void _explore_node_remove (node_ptr node); 00287 00288 void _async_loop (); 00289 void _rt_process_once (); 00290 00291 typedef std::list<sink_node_ptr> sink_node_list; 00292 typedef std::list<process_node_ptr> process_node_list; 00293 00294 core::patch_ptr _root; 00295 00296 process_node_list _procs; // Not readed from rt-threads. 00297 sink_node_list _sinks; // Readed from rt-threads. 00298 00299 full_process_context _ctx; 00300 00301 std::mutex _rt_mutex; 00302 00303 std::atomic<bool> _is_running; 00304 }; 00305 00306 } /* namespace graph */ 00307 } /* namespace psynth */ 00308 00309 #include <psynth/new_graph/processor.tpp> 00310 00311 #endif /* PSYNTH_GRAPH_PROCESSOR_HPP_ */
1.7.4