safe_list.cpp

Go to the documentation of this file.
00001 #ifndef SAFE_LIST_IMPLEMENTATION_FILE
00002 #define SAFE_LIST_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : safe_list                                                         *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1998-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "list.h"
00019 #include "node.h"
00020 #include "safe_list.h"
00021 #include "safe_node.h"
00022 
00023 #include <basis/function.h>
00024 #include <basis/mutex.h>
00025 #include <mechanisms/rw_lock.h>
00026 
00027 namespace nodes {
00028 
00029 // initialize our class constants to the proper values.
00030 const safe_list::iterator_positions safe_list::HEAD = common::HEAD;
00031 const safe_list::iterator_positions safe_list::TAIL = common::TAIL;
00032 
00033 // the real_safe_node hangs onto a safe_node from our user and allows us to
00034 // treat it like a real node by storing it in lists.
00035 
00036 class real_safe_node : public node
00037 {
00038 public:
00039   safe_node *_snode;  // holds what our users give us.
00040 
00041   real_safe_node(safe_node *to_hold) : _snode(to_hold) {}
00042   ~real_safe_node() { WHACK(_snode); }
00043 };
00044 
00046 
00047 // gives us our real iterator object to work with instead of the ugly hidden
00048 // thing.
00049 #define CAST_BACK \
00050   list::iterator &iter = *(list::iterator *)_hidden_iterator
00051 
00052 // turns the current iterator position into the real_safe_node it represents.
00053 // note that this might be NIL.
00054 #define UPCAST_NODE \
00055   real_safe_node *rsn = dynamic_cast<real_safe_node *>(iter.access())
00056 
00058 
00059 safe_list_read_iterator::safe_list_read_iterator(const safe_list &mgr,
00060     safe_list::iterator_positions where)
00061 : _manager(mgr), _hidden_iterator(NIL)
00062 {
00063   _hidden_iterator = new list::iterator(_manager._storage, NIL);
00064   CAST_BACK;
00065   if (where == safe_list::HEAD)
00066     iter = _manager._storage->head();
00067   else
00068     iter = _manager._storage->tail();
00069 }
00070 
00071 safe_list_read_iterator::~safe_list_read_iterator()
00072 {
00073   CAST_BACK;
00074   delete &iter;
00075   _hidden_iterator = NIL;
00076 }
00077 
00078 void safe_list_read_iterator::jump_head()
00079 {
00080   CAST_BACK;
00081   iter.jump_head();
00082 }
00083 
00084 void safe_list_read_iterator::jump_tail()
00085 {
00086   CAST_BACK;
00087   iter.jump_tail();
00088 }
00089 
00090 void safe_list_read_iterator::next()
00091 {
00092   CAST_BACK;
00093   iter++;
00094 }
00095 
00096 void safe_list_read_iterator::previous()
00097 {
00098   CAST_BACK;
00099   iter--;
00100 }
00101 
00102 const safe_node *safe_list_read_iterator::observe() const
00103 {
00104   CAST_BACK;
00105   UPCAST_NODE;
00106   return rsn? rsn->_snode : NIL;
00107 }
00108 
00109 bool safe_list_read_iterator::is_head()
00110 {
00111   CAST_BACK;
00112   return iter.is_head();
00113 }
00114 
00115 bool safe_list_read_iterator::is_tail()
00116 {
00117   CAST_BACK;
00118   return iter.is_tail();
00119 }
00120 
00122 
00123 safe_list_write_iterator::safe_list_write_iterator(const safe_list &mgr,
00124     safe_list::iterator_positions where)
00125 : _manager(mgr), _hidden_iterator(NIL)
00126 {
00127   _hidden_iterator = new list::iterator(_manager._storage, NIL);
00128   CAST_BACK;
00129   if (where == safe_list::HEAD)
00130     iter = _manager._storage->head();
00131   else
00132     iter = _manager._storage->tail();
00133 }
00134 
00135 safe_list_write_iterator::~safe_list_write_iterator()
00136 {
00137   CAST_BACK;
00138   delete &iter;
00139   _hidden_iterator = NIL;
00140 }
00141 
00142 void safe_list_write_iterator::jump_head()
00143 {
00144   CAST_BACK;
00145   iter.jump_head();
00146 }
00147 
00148 void safe_list_write_iterator::jump_tail()
00149 {
00150   CAST_BACK;
00151   iter.jump_tail();
00152 }
00153 
00154 void safe_list_write_iterator::next()
00155 {
00156   CAST_BACK;
00157   iter++;
00158 }
00159 
00160 void safe_list_write_iterator::previous()
00161 {
00162   CAST_BACK;
00163   iter--;
00164 }
00165 
00166 safe_node *safe_list_write_iterator::access()
00167 {
00168   CAST_BACK;
00169   UPCAST_NODE;
00170   return rsn? rsn->_snode : NIL;
00171 }
00172 
00173 bool safe_list_write_iterator::is_head()
00174 {
00175   CAST_BACK;
00176   return iter.is_head();
00177 }
00178 
00179 bool safe_list_write_iterator::is_tail()
00180 {
00181   CAST_BACK;
00182   return iter.is_tail();
00183 }
00184 
00186 
00187 safe_list::safe_list()
00188 : _storage(new list),
00189   _gate_keeper(new reader_writer_lock)
00190 {}
00191 
00192 safe_list::~safe_list()
00193 {
00194   WHACK(_storage);
00195   WHACK(_gate_keeper);
00196 }
00197 
00198 bool safe_list::empty(safe_list_read_iterator &formal(it))
00199 { return _storage->empty(); }
00200 
00201 bool safe_list::empty(safe_list_write_iterator &formal(it))
00202 { return _storage->empty(); }
00203 
00204 int safe_list::elements(safe_list_read_iterator &formal(it))
00205 { return _storage->elements(); }
00206 
00207 int safe_list::elements(safe_list_write_iterator &formal(it))
00208 { return _storage->elements(); }
00209 
00210 safe_list_read_iterator *safe_list::open_reader(iterator_positions where)
00211 {
00212   _gate_keeper->begin_read();
00213   return new safe_list_read_iterator(*this, where);
00214 }
00215 
00216 safe_list_write_iterator *safe_list::open_writer(iterator_positions where)
00217 {
00218   _gate_keeper->begin_write();
00219   return new safe_list_write_iterator(*this, where);
00220 }
00221 
00222 void safe_list::close_reader(safe_list_read_iterator * &to_close)
00223 {
00224   WHACK(to_close);
00225   _gate_keeper->end_read();
00226 }
00227 
00228 void safe_list::close_writer(safe_list_write_iterator * &to_close)
00229 {
00230   WHACK(to_close);
00231   _gate_keeper->end_write();
00232 }
00233 
00234 #define CAST_WRITER \
00235   list::iterator &iter = *(list::iterator *)writer._hidden_iterator
00236 
00237 safe_node *safe_list::remove(safe_list_write_iterator &writer)
00238 {
00239   CAST_WRITER;
00240   real_safe_node *ogre = dynamic_cast<real_safe_node *>(_storage->remove(iter));
00241   if (!ogre) return NIL;
00242   safe_node *to_return = ogre->_snode;
00243   ogre->_snode = NIL;
00244   delete ogre;
00245   return to_return;
00246 }
00247 
00248 void safe_list::zap(safe_list_write_iterator &writer)
00249 {
00250   CAST_WRITER;
00251   _storage->zap(iter);
00252 }
00253 
00254 void safe_list::insert(safe_list_write_iterator &writer, safe_node *to_insert)
00255 {
00256   CAST_WRITER;
00257   real_safe_node *to_add = new real_safe_node(to_insert);
00258   _storage->insert(iter, to_add);
00259 }
00260 
00261 } // namespace
00262 
00263 #endif //SAFE_LIST_IMPLEMENTATION_FILE
00264 

Generated on Fri Nov 21 04:29:51 2008 for HOOPLE Libraries by  doxygen 1.5.1