// -*- c++ -*-
/*
Copyright 2000, Karl Einar Nelson
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sigc++/signal.h"
#ifdef SIGC_CXX_NAMESPACES
namespace SigC
{
#endif
class SignalConnectionNode;
class SignalIterator_;
// Signal_ comes from Slot_, but it lacks a proxy until added by
// the holding Signal<>, which does so on a request of the user.
// Thus you must use the conversion operator on a Signal to get a Slot.
SignalNode::SignalNode()
: SlotNode(0), exec_count_(0), begin_(0), end_(0)
{
reference();
}
SignalNode::~SignalNode()
{ clear(); }
void SignalNode::clear()
{
if (!exec_count_)
{
SignalConnectionNode *i=begin_,*j;
begin_=end_=0;
while (i)
{
j=i->next_;
i->parent_ = 0;
i->unreference();
i=j;
}
}
else
{
SignalConnectionNode *i=begin_;
while (i)
{
i->defered_=true;
i->blocked_=true;
i=i->next_;
}
defered_=true;
}
}
bool SignalNode::empty()
{ return !begin_; }
/*
void Signal_::exec_reference()
{
reference();
exec_count_+=1;
}
void Signal_::exec_unreference()
{
if (!--exec_count_)
cleanup();
unreference();
}
*/
void SignalNode::cleanup()
{
if(!defered_)
return;
defered_ = false;
SignalConnectionNode* i = begin_;
while(i)
{
SignalConnectionNode* next = i->next_;
if(i->defered_)
_remove(i);
i = next;
}
}
SlotNode* SignalNode::create_slot(FuncPtr proxy) // nothrow
{
proxy_=proxy;
return this;
}
ConnectionNode* SignalNode::push_front(const SlotBase& s)
{
SignalConnectionNode* c=new SignalConnectionNode((SlotNode*)(s.impl()));
c->reference();
c->parent_=this;
c->next_=begin_;
if (begin_)
begin_->prev_=c;
else
end_=c;
begin_=c;
return c;
}
ConnectionNode* SignalNode::push_back(const SlotBase& s)
{
SignalConnectionNode* c=new SignalConnectionNode((SlotNode*)(s.impl()));
c->reference();
c->parent_=this;
c->prev_=end_;
if (end_)
end_->next_=c;
else
begin_=c;
end_=c;
return c;
}
void SignalNode::remove(SignalConnectionNode* c)
{
if(!exec_count_)
_remove(c);
else
{
c->defered_=true;
c->blocked_=true;
defered_=true;
}
}
void SignalNode::_remove(SignalConnectionNode* c)
{
if (c->prev_)
c->prev_->next_=c->next_;
else
begin_=c->next_;
if (c->next_)
c->next_->prev_=c->prev_;
else
end_=c->prev_;
c->parent_ = 0;
c->unreference();
}
/**********************************************************/
SignalBase::SignalBase()
: impl_(0)
{}
SignalBase::SignalBase(const SignalBase& s)
: impl_(s.impl())
{
impl_->reference();
}
SignalBase::SignalBase(SignalNode* s)
: impl_(s)
{
if (s)
impl_->reference();
}
SignalBase::~SignalBase()
{
if (impl_)
impl_->unreference();
}
SignalNode* SignalBase::impl() const
{
if (!impl_)
impl_=new SignalNode();
return impl_;
}
/**********************************************************/
void SignalConnectionNode::notify(bool from_child)
{
Node n (this);
ConnectionNode::notify(from_child);
if(parent_) // this node might have been removed already
parent_->remove(this);
}
SignalConnectionNode::~SignalConnectionNode()
{ }
SignalConnectionNode::SignalConnectionNode(SlotNode* s)
: ConnectionNode(s), parent_(0), next_(0), prev_(0)
{ }
#ifdef SIGC_CXX_NAMESPACES
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1