gnucap-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnucap-devel] Modified version of l_dispatcher.h -- please try it.


From: al davis
Subject: [Gnucap-devel] Modified version of l_dispatcher.h -- please try it.
Date: Sun, 4 Mar 2007 20:55:26 -0500
User-agent: KMail/1.9.5

This is a modified version, that uses a pointer work-around,
hopefully taking care of the initialization order issue.

It works for the cases I tried ..  I was able to move globals.o to either 
end of the link list and it works both places.

There are still some theoretical issues.  I am not sure whether this
is actually an improvement in all cases, because the impact is less 
predictable.

For this to work, it essential that class DISPATCHER does not have 
a constructor or destructor.  Then it makes the assumption of
C-style initialization.  For every C++ compiler I have seen, this is 
true, but it is not guraranteed by the standard,

If DISPATCHER has a constructor, it could be called after the
manual initialization already happened, wiping it out.

If the link order is correct, as defined as resulting in the correct 
construction order, this version should work the same as before.
If the link order is incorrect, as defined as resulting in an incorrect
construction order, this version seems to hide the problem, so it 
only shows when compiled with all debugging turned on.



/*$Id: l_dispatcher.h,v 26.18 2007/03/03 06:08:43 al Exp $ -*- C++ -*-
 * Copyright (C) 2006 Albert Davis
 * Author: Albert Davis <address@hidden>
 *
 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
 *
 * 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *------------------------------------------------------------------
 * dispatcher -- for dynamically loaded modules
 */
//testing=informal
#ifndef L_DISPATCHER_H
#define L_DISPATCHER_H
#include "l_lib.h"
#include "l_stlextra.h"
#include "ap.h"
/*--------------------------------------------------------------------------*/
template <class T>
class DISPATCHER {
private:
  //std::map<std::string, T*> _map;
  std::map<std::string, T*> * _map;
public:
  void install(const std::string& s, T* p) {
    if (!_map) {
      _map = new std::map<std::string, T*>;
    }else{
    }
    trace0(s.c_str());
    for (std::string::size_type
         begin = 0, end = s.find(',', begin);
         begin != std::string::npos;
         begin = (end != std::string::npos) ? end+1 : std::string::npos,
           end = s.find(',', begin)) {
      std::string name = s.substr(begin, 
                (end != std::string::npos) ? end-begin : std::string::npos);
      trace2(name.c_str(), begin, end);
      if (name == "") {
        // quietly ignore empty string
      }else if ((*_map)[name]) {
        error(bWARNING, name + ": already installed, replacing\n");
        // stash the old one so we can get it back
        std::string save_name = name + ":0";
        for (int ii = 0; (*_map)[save_name]; ++ii) {
          save_name = name + ":" + to_string(ii);
        }
        (*_map)[save_name] = (*_map)[name];     
        error(bWARNING, "stashing as " + save_name + "\n");
      }else{
      }
      (*_map)[name] = p;
    }
  }
  
  void uninstall(const std::string& s) {
    assert(_map);
    for (std::string::size_type
         begin = 0, end = s.find(',', begin);
         begin != std::string::npos;
         begin = (end != std::string::npos) ? end+1 : std::string::npos,
           end = s.find(',', begin)) {
      std::string name = s.substr(begin,
                (end != std::string::npos) ? end-begin : std::string::npos);
      if (name == "") {
        // quietly ignore empty string
      }else if ((*_map)[name]) {
        // delete, try to get back the old one
        int ii = 0;
        std::string save_name = name + ":0";
        for (ii = 0; (*_map)[save_name]; ++ii) {
          save_name = name + ":" + to_string(ii);
        }
        if (ii > 1) {
          save_name = name + ":" + to_string(ii-2);
          (*_map)[name] = (*_map)[save_name];
          (*_map)[save_name] = NULL;
          error(bWARNING, "restoring " + save_name + " as " + name + "\n");
        }else{
          (*_map)[name] = NULL;
        }
      }else{
        error(bWARNING, name + ": not installed, doing nothing\n");
      }
    }
  }

  T* operator[](const std::string& s) {
    assert(_map);
    return (*_map)[s];
  }

  T* operator[](CS& cmd) {
    int here = cmd.cursor();
    std::string s;
    cmd >> s;
    notstd::to_lower(&s);
    //------------------------
    T* p = (*this)[s];
    //------------------------
    if (!p) {
      cmd.reset(here);
    }else{
    }
    return p;
  }

  class INSTALL {
  private:
    const std::string _name;
    DISPATCHER<T>* _d;
  public:
    INSTALL(DISPATCHER<T>* d, const std::string& name, T* p) :
      _name(name),
      _d(d) 
    {
      assert(_d);
      assert(p);
      _d->install(_name, p);
    }
    
    ~INSTALL() {
      _d->uninstall(_name);
    }
  };
};
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
#endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]