//# Notice.h: Classes for manipulating notices //# Copyright (C) 1993,1994,1995,1999,2002 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library 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 Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_NOTICE_H #define CASA_NOTICE_H #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN //# Forward Declaration class NoticeTarget; // abstract base class for notices // // // // // A Notice is the piece of information passed around // between a NoticeSource and a NoticeTarget. This // abstract base class is only a skeleton intended to be derived from. It // does not contain any relevant information -- that must be added by // the derived classes --, but it enforces derived classes to implement // the comparison operator == and the function // type(). // // // ListNotice, derived from // Notice, is the notification which is passed between // List and // ListIter // to keep cursors and container in sync. // class Notice { public: Notice() {} virtual ~Notice(); // Compare two Notices. virtual bool operator==(const Notice &) const = 0; }; // base class for notice originators // // // // // A NoticeSource maintains a list of all of the // NoticeTargets which are interested in Notices // from this NoticeSource. Its member function // notify() sends the specified Notice to all the // NoticeTargets in the list. // // Classes which have many other dependent objects which need to be // updated, should derive from this class. // // // List, the linked list class, is // derived from NoticeSource. It mainly contains status // information; all the manipulation functions are located in the // ListIter classes. The linked // list and its iterators communicate with each other via the notice // system. List does not provide any further notice // functionality; everything is taken care of by its base class // NoticeSource. // class NoticeSource { public: friend class NoticeTarget; NoticeSource() : curIters(0) {} virtual ~NoticeSource(); // Sends the note to all NoticeTargets in the // target list. void notify(const Notice & note); private: Link *curIters; //# Do not Delete Link *&head() { return curIters;} }; // abstract base class for notice receptors // // // // // A NoticeTarget receives the Notices from the // NoticeSource to which it is linked. A target can only be // linked to one source. // // Classes which are dependent upon a particular // NoticeSource should derive from this class. // // // ListIter and its parent class // ConstListIter are the iterators or // "dynamic" cursors in the linked List. They // are derived from NoticeTarget, and the notice system ensures // that multiple cursors are updated as elements are added and removed from // the list, according to the following scheme: //
    //
  1. An iterator changes something to the underlying list. //
  2. The iterator creates a ListNotice // containing all the necessary information about the change. //
  3. The iterator passes the notice to the NoticeSource // List. //
  4. The list relays the notice to all other iterators operating on the // list (kept in the "target list"). //
  5. Every iterator catches the notice and changes its state accordingly. //
//
class NoticeTarget { public: friend class NoticeSource; // Destructs this NoticeTarget. virtual ~NoticeTarget(); // Returns a boolean value telling whether this NoticeTarget // is still "valid". Bool isValid() const {return valid;} // Returns a boolean value telling whether this NoticeTarget // is still attached to a NoticeSource or not. Bool isAttached() const {return ilink ? True : False;} // Makes the current NoticeTarget "invalid". void invalidate() {valid = False;} // Hook through which NoticeTargets are notified // (by NoticeSources). virtual void notify(const Notice &) = 0; protected: Link *ilink; NoticeSource *container; Bool valid; // Creates an unlinked, "invalid" NoticeTarget. An invalid // NoticeTarget does not occur in the target list of any // NoticeSource. NoticeTarget() : ilink(0), container(0), valid(False) {} // Creates a "valid" NoticeTarget linked to the specified // NoticeSource. The NoticeTarget will be added // to the target list in that NoticeSource. // NoticeTarget(NoticeSource *v) : ilink(0), container(0), valid(False) {attach(v);} NoticeTarget(NoticeSource &v) : ilink(0),container(0), valid(False) {attach(v);} // // Creates a "valid" NoticeTarget linked to the same // NoticeSource as the other NoticeTarget. // So, both NoticeTargets will occur in the same target // list. // NoticeTarget(NoticeTarget &other) : ilink(0), container(0), valid(False) { if (other.isValid()) attach(other.container);} NoticeTarget(NoticeTarget *other) : ilink(0), container(0), valid(False) { if (other && other->isValid()) attach( (*other).container );} // // Unlinks this NoticeTarget from its NoticeSource. // The NoticeTarget will be removed from the target list. void unlink(); // Links this NoticeTarget to the same NoticeSource // as the other NoticeTarget. Any previous link will be undone. // void link(const NoticeTarget &other); void link(const NoticeTarget *other); // // Retrieves the next NoticeTarget in the target list // of the associated NoticeSource. // Link *next() { return(ilink ? (*ilink).next() : 0); } const Link *next() const { return(ilink ? (*ilink).next() : 0); } // // Adds this NoticeTarget to the target list in the // specified NoticeSource, so that it will receive all // notices sent out by that NoticeSource. // void attach(NoticeSource *v); void attach(NoticeSource &v); // }; } //# NAMESPACE CASACORE - END #endif