/* * Copyright (C) 2006-2016 Jacek Sieka, arnetheduck on gmail point 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 * (at your option) 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ADCHPP_SIGNAL_H #define ADCHPP_SIGNAL_H namespace adchpp { struct Connection : private boost::noncopyable { public: Connection() { } virtual ~Connection() { } virtual void disconnect() = 0; }; typedef std::unique_ptr ConnectionPtr; template class Signal { public: typedef std::function Slot; typedef std::list SlotList; typedef F FunctionType; template void operator()(T0&& t0) { for(auto i = slots.begin(), iend = slots.end(); i != iend;) { (*i++)(std::forward(t0)); } } template void operator()(T0&& t0, T1&& t1) { for(auto i = slots.begin(), iend = slots.end(); i != iend;) { (*i++)(std::forward(t0), std::forward(t1)); } } template void operator()(T0&& t0, T1&& t1, T2&& t2) { for(auto i = slots.begin(), iend = slots.end(); i != iend;) { (*i++)(std::forward(t0), std::forward(t1), std::forward(t2)); } } template ConnectionPtr connect(const T& f) { return ConnectionPtr(new SlotConnection(this, slots.insert(slots.end(), f))); } ~Signal() { } private: SlotList slots; void disconnect(const typename SlotList::iterator& i) { slots.erase(i); } struct SlotConnection : public Connection { SlotConnection(Signal* sig_, const typename SlotList::iterator& i_) : sig(sig_), i(i_) { } virtual void disconnect() { if(sig) sig->disconnect(i), sig = 0; } Signal* sig; typename Signal::SlotList::iterator i; }; }; struct ManagedConnection : private boost::noncopyable { ManagedConnection(ConnectionPtr&& conn_) : conn(move(conn_)) { } void disconnect() { if(conn.get()) { conn->disconnect(); conn.reset(); } } void release() { conn.reset(); } ~ManagedConnection() { disconnect(); } private: ConnectionPtr conn; }; typedef shared_ptr ManagedConnectionPtr; template inline ManagedConnectionPtr manage(Signal* signal, const F2& f) { return make_shared(signal->connect(f)); } inline ManagedConnectionPtr manage(ConnectionPtr && conn) { return make_shared(move(conn)); } template struct SignalTraits { typedef adchpp::Signal Signal; typedef adchpp::ConnectionPtr Connection; typedef adchpp::ManagedConnectionPtr ManagedConnection; }; } #endif // SIGNAL_H