|
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_PORT_HPP_ 00032 #define PSYNTH_PORT_HPP_ 00033 00034 #include <map> 00035 #include <list> 00036 #include <atomic> 00037 #include <iostream> // FIXME: remove 00038 00039 #include <boost/any.hpp> 00040 #include <boost/range/iterator_range.hpp> 00041 #include <boost/intrusive/list.hpp> 00042 00043 #include <psynth/base/type_value.hpp> 00044 #include <psynth/base/iterator.hpp> 00045 #include <psynth/new_graph/exception.hpp> 00046 #include <psynth/new_graph/node_fwd.hpp> 00047 #include <psynth/new_graph/processor_fwd.hpp> 00048 00049 namespace psynth 00050 { 00051 namespace graph 00052 { 00053 00054 PSYNTH_DECLARE_ERROR (error, port_error); 00055 PSYNTH_DECLARE_ERROR (port_error, port_type_error); 00056 PSYNTH_DECLARE_ERROR (port_error, port_patch_error); 00057 00058 typedef std::map<std::string, boost::any> port_meta; 00059 extern const port_meta default_port_meta; 00060 00061 class out_port_base; 00062 class in_port_base; 00063 00064 class port_base : private boost::noncopyable 00065 { 00066 public: 00067 virtual base::type_value type () const = 0; 00068 virtual const port_meta& meta () const = 0; 00069 virtual void rt_context_update (rt_process_context&) {} 00070 00071 std::string name () 00072 { return _name; } 00073 00074 node& owner () 00075 { return *_owner; } 00076 const node& owner () const 00077 { return *_owner; } 00078 00079 void _set_owner (node* new_owner = 0); 00080 void _set_name (std::string new_name); 00081 bool _has_owner () const 00082 { return _owner != 0; } 00083 00084 protected: 00085 port_base (std::string name, node* owner); 00086 00087 private: 00088 std::string _name; 00089 node* _owner; 00090 }; 00091 00092 struct out_port_referee_hook_tag; 00093 typedef boost::intrusive::list_member_hook< 00094 boost::intrusive::link_mode<boost::intrusive::auto_unlink>, 00095 boost::intrusive::tag<out_port_referee_hook_tag> 00096 > 00097 out_port_referee_hook; 00098 00099 void check_port_compatibility (in_port_base& in, out_port_base& out); 00100 00101 class in_port_base : public port_base 00102 { 00103 public: 00104 out_port_referee_hook _out_port_referee_hook; 00105 00106 virtual void connect (out_port_base& port); 00107 virtual void disconnect (); 00108 00109 bool connected () const 00110 { return _source_port != 0; } 00111 bool rt_connected () const 00112 { return _rt_source_port != 0; } 00113 00114 out_port_base& source () 00115 { return *_source_port; } 00116 out_port_base& rt_source () 00117 { return *_rt_source_port; } 00118 const out_port_base& source () const 00119 { return *_source_port; } 00120 const out_port_base& rt_source () const 00121 { return *_rt_source_port; } 00122 00123 virtual bool rt_in_available () const; 00124 virtual void rt_process (rt_process_context& rt); 00125 00126 protected: 00127 in_port_base (std::string name, graph::node* owner); 00128 00133 void _connect (out_port_base* source); 00134 void _user_connect (out_port_base* source); 00135 void _rt_connect (out_port_base* source); 00136 00137 private: 00138 out_port_base* _source_port; 00139 out_port_base* _rt_source_port; 00140 }; 00141 00142 namespace detail { class out_port_access; } 00143 00144 class out_port_base : public port_base 00145 { 00146 typedef std::list<in_port_base*> reference_list; 00147 typedef boost::intrusive::list< 00148 in_port_base, 00149 boost::intrusive::constant_time_size<false>, 00150 boost::intrusive::member_hook< 00151 in_port_base, 00152 out_port_referee_hook, 00153 &in_port_base::_out_port_referee_hook> > 00154 rt_reference_list; 00155 00156 public: 00157 typedef base::ptr_iterator<reference_list::iterator> 00158 reference_iterator; 00159 typedef base::ptr_iterator<reference_list::const_iterator> 00160 reference_const_iterator; 00161 typedef boost::iterator_range<reference_iterator> 00162 reference_range; 00163 typedef boost::iterator_range<reference_const_iterator> 00164 const_reference_range; 00165 00166 void disconnect (); 00167 00168 bool connected () 00169 { return !_refs.empty (); } 00170 00171 bool rt_connected () 00172 { return !_rt_refs.empty (); } 00173 // FIXME: Add concurrent access to refs policy 00174 00175 virtual bool rt_out_available () const 00176 { return true; } 00177 00178 reference_range references () 00179 { return reference_range (_refs.begin (), _refs.end ()); } 00180 const_reference_range references () const 00181 { return const_reference_range (_refs.begin (), _refs.end ()); } 00182 00183 protected: 00184 out_port_base (std::string name, node* owner); 00185 00186 private: 00187 void _add_reference (in_port_base*); 00188 void _del_reference (in_port_base*); 00189 00190 friend class detail::out_port_access; 00191 00192 reference_list _refs; 00193 rt_reference_list _rt_refs; 00194 }; 00195 00196 namespace detail 00197 { 00198 00199 struct out_port_access 00200 { 00201 static void add_reference (out_port_base& self, in_port_base* param) 00202 { self._add_reference (param); } 00203 00204 static void del_reference (out_port_base& self, in_port_base* param) 00205 { self._del_reference (param); } 00206 }; 00207 00208 } /* namespace detail */ 00209 00210 template <typename T> 00211 class typed_out_port_base : public out_port_base 00212 { 00213 public: 00214 typedef T port_type; 00215 00216 virtual T& rt_get_out () = 0; 00217 virtual const T& rt_get_out () const = 0; 00218 00219 base::type_value type () const 00220 { return typeid (T); } 00221 00222 protected: 00223 typed_out_port_base (std::string name, node* owner) 00224 : out_port_base (name, owner) {} 00225 }; 00226 00227 template <typename T> 00228 class typed_in_port_base : public in_port_base 00229 { 00230 public: 00231 typedef T port_type; 00232 00233 virtual const T& rt_get_in () const = 0; 00234 00235 base::type_value type () const 00236 { return typeid (T); } 00237 00238 protected: 00239 typed_in_port_base (std::string name, node* owner) 00240 : in_port_base (name, owner) {} 00241 }; 00242 00243 template <typename T> 00244 class out_port : public typed_out_port_base<T> 00245 { 00246 public: 00247 typedef T port_type; 00248 00249 out_port (std::string name, node* owner, const T& value = T()) 00250 : typed_out_port_base<T> (name, owner) 00251 , _data (value){} 00252 00253 T& rt_get_out () 00254 { return _data; } 00255 00256 const T& rt_get_out () const 00257 { return _data; } 00258 00259 const port_meta& meta () const 00260 { return default_port_meta; } // FIXME !!! 00261 00262 private: 00263 T _data; 00264 }; 00265 00266 template <typename T> 00267 class in_port : public typed_in_port_base<T> 00268 { 00269 public: 00270 in_port (std::string name, node* owner) 00271 : typed_in_port_base<T> (name, owner) {} 00272 00273 const port_meta& meta () const 00274 { return default_port_meta; } // FIXME !!! 00275 00276 const T& rt_get_in () const 00277 { 00278 // Relies on the connection being made right! 00279 return static_cast<const out_port<T>&> ( 00280 this->rt_source ()).rt_get_out (); 00281 } 00282 00283 private: 00284 }; 00285 00290 template <class InPort, 00291 class OutPort> 00292 class forward_port_impl 00293 : public InPort 00294 , public OutPort 00295 { 00296 public: 00297 typedef typename InPort::port_type port_type; 00298 00299 static_assert ( 00300 std::is_same<typename InPort::port_type, 00301 typename OutPort::port_type>::value, 00302 "Can not forward different types"); 00303 00304 void rt_context_update (rt_process_context& ctx) 00305 { 00306 InPort::rt_context_update (ctx); 00307 OutPort::rt_context_update (ctx); 00308 } 00309 00310 base::type_value type () const 00311 { return typeid (port_type); } 00312 00313 const port_meta& meta () const 00314 { return default_port_meta; } // FIXME !!! 00315 00316 const port_type& rt_get_out () const 00317 { 00318 if (InPort::rt_connected ()) 00319 return this->rt_get_in (); 00320 return OutPort::rt_get_out (); 00321 } 00322 00323 bool rt_out_available () const 00324 { return InPort::rt_connected (); } 00325 00326 protected: 00327 forward_port_impl (std::string in_name, 00328 std::string out_name, 00329 node* in_owner, 00330 node* out_owner) 00331 : InPort (in_name, in_owner) 00332 , OutPort (out_name, out_owner) 00333 {} 00334 }; 00335 00336 template <typename T> 00337 struct forward_port 00338 : public forward_port_impl<in_port<T>, 00339 out_port<T> > 00340 { 00341 typedef forward_port_impl<in_port<T>, out_port<T> > base_type; 00342 00343 forward_port (std::string in_name, 00344 std::string out_name, 00345 node* in_owner, 00346 node* out_owner) 00347 : base_type (in_name, out_name, 00348 in_owner, out_owner) 00349 {} 00350 }; 00351 00352 } /* namespace graph */ 00353 } /* namespace psynth */ 00354 00355 #include <psynth/new_graph/port.tpp> 00356 00357 #endif /* PSYNTH_PORT_HPP_ */
1.7.4