4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 // Stefan Bund <stefan.bund@fokus.fraunhofer.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 // Definition of non-inline non-template functions
29 #include <boost/utility.hpp> // for next/prior
32 ///////////////////////////////cc.p////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////////////
38 // We manage TWO reference counts:
40 // - The first reference counts lives wihin PacketImpl. It counts the
41 // number of references to the PacketImpl instance
43 // - The second reference count lives with the Packet interpreters. It
44 // counts the number of external references to the Packet facades.
46 // The PacketImpl refcount is always the sum of all it's Packet
47 // interpreter member refcounts.
49 // The Packet facades are referenced from two sides:
51 // - From the user. These references are counted in the Packet
54 // - From the list of interpreters. These references are *not*
57 // The Packet facades have an impl_ member. This is set to non-0 only,
58 // as long as the Packet is a list member. The Packet may be deleted,
59 // when impl_ == 0 and refcount_ == 0.
61 // class ListPacketDeleter
63 // This is the custom deleter used for the pointers in the
64 // interpreters list. This deleter is only called, when the Packet is
65 // removed from the interpreters list.
66 prefix_ void senf::impl::ListPacketDeleter::operator()(Packet * p)
68 PacketImpl * impl = PacketImpl::impl(p);
69 if (impl->releaseInterpreter(p))
75 prefix_ senf::Packet::interpreter_list::iterator
76 senf::impl::PacketImpl::appendInterpreter(Packet * p)
78 BOOST_ASSERT( p->impl_ == 0 );
80 this->refcount_ += p->refcount_;
81 SATCOM_PKF_REFC_MSG("] PacketImpl::appendInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
83 this->interpreters_.push_back(
84 boost::shared_ptr<Packet>(p, impl::ListPacketDeleter()));
86 p->self_ = boost::prior(this->interpreters_.end());
90 prefix_ senf::Packet::interpreter_list::iterator
91 senf::impl::PacketImpl::prependInterpreter(Packet * p)
93 BOOST_ASSERT( p->impl_ == 0 );
95 this->refcount_ += p->refcount_;
96 SATCOM_PKF_REFC_MSG("] PacketImpl::prependInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
98 this->interpreters_.push_front(
99 boost::shared_ptr<Packet>(p, impl::ListPacketDeleter()));
101 p->self_ = this->interpreters_.begin();
105 // Called, whenever a Packet is removed from the list by the
106 // ListPacketDeleter;
107 prefix_ bool senf::impl::PacketImpl::releaseInterpreter(Packet * p)
109 // We have to be extra careful here: This method might be called
110 // AFTER the PacketImpl instance has already been destructed while
111 // destructing the interpreters list !!
112 // If p->refcount_ is > 0 however we know, that this->refcount_
113 // must also be > 0 ...
114 // So we have to make sure never to access this if p->refcount_==0
115 BOOST_ASSERT( p->impl_ == this );
117 if (p->refcount_ > 0) {
118 this->refcount_ -= p->refcount_;
119 rv = !this->refcount_;
120 SATCOM_PKF_REFC_MSG("] PacketImpl::releaseInterpreter (" << this << "): refcount_ = " << refcount_ << "\n");
128 bool whenceCmp(unsigned a, unsigned b, bool end, senf::Packet::Whence whence)
131 return ((whence == Packet::OUTSIDE && ! end)
132 || whence == Packet::BEFORE
133 || (whence == Packet::INSIDE && end)) ? a>=b : a>b;
138 senf::impl::PacketImpl::updateIterators(Packet::size_type index,
139 Packet::difference_type n,
140 Packet::interpreter_list::iterator self,
141 Packet::Whence whence)
143 Packet::interpreter_list::iterator i (interpreters_.begin());
144 Packet::interpreter_list::iterator const e (interpreters_.end());
145 Packet::Whence w (whence == Packet::AUTO ? Packet::INSIDE : whence);
147 if (whenceCmp((*i)->end_,index,true,w))
148 if (n<0 && (*i)->end_ < index-n)
152 if (whenceCmp((*i)->begin_,index,false,w))
153 if (n<0 && (*i)->begin_ < index-n)
154 (*i)->begin_ = index;
157 if (i == self && whence == Packet::AUTO) w = Packet::OUTSIDE;
158 BOOST_ASSERT( (*i)->end_ >= (*i)->begin_ );
162 prefix_ void senf::impl::PacketImpl::packet_add_ref(Packet const * p)
169 prefix_ void senf::impl::PacketImpl::packet_release(Packet * p)
171 bool del (p->release());
172 if (p->impl_ && p->impl_->release())
173 // In this case, del is certainly false here. p might
174 // however get deleted now.
180 ///////////////////////////////////////////////////////////////////////////
183 prefix_ senf::Packet::ptr senf::Packet::next()
186 interpreter_list::iterator n = boost::next(this->self_);
187 if (n == this->impl_->interpreters_.end()) {
190 /* \fixme v_nextInterpreter return bool? new Interpreter to be
191 added ? hmm ... this however is quite suboptimal ... */
192 this->v_nextInterpreter();
193 this->parsed_ = true;
194 n = boost::next(this->self_);
195 if (n == this->impl_->interpreters_.end())
198 // Re-converting the Packet to a smart pointer is correct here,
199 // since the shared_ptr really uses the intrusive refcount which
200 // makes this operation safe ...
201 return ptr(n->get(),true);
204 prefix_ senf::Packet::ptr senf::Packet::last()
207 Packet * p = this->impl_->interpreters_.back().get();
208 while (! p->parsed_) {
209 Packet * pp = p->next().get();
212 // Re-converting the to a smart pointer is correct here, since the
213 // shared_ptr really uses the intrusive refcount which makes this
214 // operation safe ...
218 prefix_ void senf::Packet::i_registerInterpreter(Packet * p)
221 BOOST_ASSERT( !p->impl_ );
222 this->impl_->truncateInterpretersAfter(this);
223 this->impl_->appendInterpreter(p);
224 this->parsed_ = true;
227 prefix_ void senf::Packet::i_replaceInterpreter(Packet * p)
229 BOOST_ASSERT( !p->impl_ );
230 // We need to increment the refcount of impl_ beforehand,
231 // otherwise it might get deleted by the truncateInterpreters call
232 boost::intrusive_ptr<impl::PacketImpl> impl (this->impl_,true);
233 impl->truncateInterpreters(this);
234 impl->appendInterpreter(p);
237 prefix_ void senf::Packet::i_setInterpreter(impl::PacketImpl * i)
239 // Using prependInterpreter makes this usable for both, the
240 // create-from-data and wrap-packet constructors
241 i->prependInterpreter(this);
244 prefix_ void senf::Packet::insert(iterator pos, byte v, Whence whence)
246 size_type index(pos-impl_->data_.begin());
247 BOOST_ASSERT( index >= begin_ && index <= end_);
248 impl_->data_.insert(pos,v);
249 impl_->updateIterators(index,1,self_,whence);
252 prefix_ void senf::Packet::insert(iterator pos, size_type n, byte v, Whence whence)
254 size_type index(pos-impl_->data_.begin());
255 BOOST_ASSERT( index >= begin_ && index <= end_ );
256 impl_->data_.insert(pos,n,v);
257 impl_->updateIterators(index,n,self_,whence);
260 prefix_ void senf::Packet::erase(iterator pos)
262 size_type index(pos-impl_->data_.begin());
263 BOOST_ASSERT( index >= begin_ && index < end_ );
264 impl_->data_.erase(pos);
265 impl_->updateIterators(index,-1,self_,INSIDE);
268 prefix_ void senf::Packet::erase(iterator first, iterator last)
270 size_type index(first-impl_->data_.begin());
271 size_type sz(last-first);
272 BOOST_ASSERT( index >= begin_ && index < end_ && sz <= end_-index );
273 /** \todo Here we should assert, that no bytes belonging to the
274 next iterator are deleted ... */
275 impl_->data_.erase(first,last);
276 impl_->updateIterators(index,-sz,self_,INSIDE);
279 prefix_ void senf::Packet::dump(std::ostream & os)
288 //////////////////////////////cc.e////////////////////////////////////////
295 // c-file-style: "senf"
296 // indent-tabs-mode: nil
297 // ispell-local-dictionary: "american"