[Enhance threadsafety of Hooks and improve generally
clinton@unknownlamer.org**20081115210917
 * bot:addhook may now be called from within a hook
   - hook mutex is recursive
   - It is unspecified whether a newly added hook will first run on the
     current or next hook match; depending on the properties of the
     hook either may occur
 * Use general sorted list utilities instead of pushing to the back and
   doing a full sort on each add
 * Incidentally replace String usage with std::string
] {
hunk ./source/BotInterp.C 69
-  : bot(b), counter(0), timer_mutex (true)
+  : bot(b), counter(0), 
+    hook_mutex (true), timer_mutex (true)
hunk ./source/BotInterp.C 98
-  bool hptr_lt (const Hook* h, const Hook* h1)
-    // Hook Pointer less than
-    // Used to sort the Hooks list
-  { return *h < *h1; }
+  struct HookFind
+  {
+    std::string rx;
+    std::string name;
+
+    HookFind (std::string r, std::string n)
+      : rx (r), name (n)
+    { }
+
+    bool operator() (const Hook * hook) const
+    { return hook->regex_str == rx && hook->name == name; }
+  };
hunk ./source/BotInterp.C 114
-		   String name) 
+		   std::string name) 
hunk ./source/BotInterp.C 118
-  String rx = Utils::to_upper (Utils::scm2str (regex));
-  // fixme: really ought to use scm_c_module_lookup with bot module
+
+  BotLock hook_lock (hook_mutex);
+  std::string rx = Utils::to_upper (Utils::scm2str (regex));
hunk ./source/BotInterp.C 124
+  HookFind hook_find (rx, name);
+  HookList& hook_list = hooks[hooktype];
+
hunk ./source/BotInterp.C 130
-  BotLock hook_lock (hook_mutex);
-
-  // First, we check if an hook doesn't exist yet
-  std::list<Hook *>::iterator it = hooksMap[hooktype].begin();
-  std::list<Hook *>::iterator it2 = hooksMap[hooktype].end();
+  HookList::iterator it = std::find_if (hook_list.begin (),
+					hook_list.end (),
+					hook_find);
+						 
+  if (it != hook_list.end())
+    {
+      Hook * found = *it;
hunk ./source/BotInterp.C 138
-  for ( ; it != it2; ++it)
-    // It exists, we replace it.
-    if ((*it)->regex_str == rx && (*it)->name == name) {
-      scm_gc_unprotect_object((*it)->function);
+      scm_gc_unprotect_object(found->function);
hunk ./source/BotInterp.C 140
-      (*it)->function = function;
-      (*it)->priority = pri;
-      (*it)->fallthru = fall;
-      hooksMap[hooktype].sort (hptr_lt);
+
+      found->function = function;
+      found->priority = pri;
+      found->fallthru = fall;
+
+      hook_list.erase (it);
+      Utils::push_sorted (hook_list, found, hook_sort_p);
+
+      return true;
+    }
+  else
+    {
+      Utils::push_sorted (hook_list,
+			  new Hook(hooktype, rx, r, function, pri, fall, name),
+			  hook_sort_p);
+      
hunk ./source/BotInterp.C 158
-  // It does not exist, we create it
-  hooksMap[hooktype].push_back (new Hook(hooktype, rx, r, 
-					 function, pri, fall, name));
-  hooksMap[hooktype].sort (hptr_lt);
-  return true;
hunk ./source/BotInterp.C 161
-BotInterp::RunHooks(int hooktype, String match, SCM args)
+BotInterp::RunHooks(int hooktype, std::string match, SCM args)
hunk ./source/BotInterp.C 166
-
-  // We want to execute higher priority hooks first, so we start at
-  // the end of the list instead of the beggining
-  std::list<Hook *>::reverse_iterator it = hooksMap[hooktype].rbegin();
-  std::list<Hook *>::reverse_iterator it2 = hooksMap[hooktype].rend();
-
hunk ./source/BotInterp.C 169
-  for ( ; it != it2; ++it) {
-    if (scm_regexp_exec((*it)->regex, Utils::str2scm (match),
-                        SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F)
-      {
-	wd.func = (*it)->function;
-	result = scm_internal_catch(SCM_BOOL_T, 
-				    (scm_t_catch_body) 
-				    Interp::LazyApplyWrapper,
-				    static_cast<void *> (&wd), 
-				    (scm_t_catch_handler) Interp::EmptyHandler, 0);
-	if (! (*it)->fallthru)
-	  break;
+  // We want to execute higher priority hooks first, so we start at
+  // the end of the list instead of the beginning
+  
+  for (HookList::reverse_iterator it = hooks[hooktype].rbegin();
+       it != hooks[hooktype].rend();
+       ++it) 
+    {
+      std::cerr << "Matching...\n";
+      if (scm_regexp_exec((*it)->regex, Utils::str2scm (match),
+			  SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F)
+	{
+	  std::cerr << " Match " << (*it)->regex_str << std::endl;
+	  bool fallthru_p = (*it)->fallthru;
+	  wd.func = (*it)->function;
+	  result = scm_internal_catch(SCM_BOOL_T, 
+				      (scm_t_catch_body) 
+				      Interp::LazyApplyWrapper,
+				      static_cast<void *> (&wd), 
+				      (scm_t_catch_handler) Interp::EmptyHandler, 0);
+	  if (!fallthru_p)
+	    break;
+	}
hunk ./source/BotInterp.C 192
-  }
-
+  
hunk ./source/BotInterp.H 30
-#include <map>
-#include <list>
hunk ./source/BotInterp.H 31
+#include <list>
+#include <map>
+#include <string>
hunk ./source/BotInterp.H 48
-  String regex_str;
-  String name;
+  std::string regex_str;
+  std::string name;
hunk ./source/BotInterp.H 53
-  Hook(int t, String rs, SCM r, SCM f, int p, bool ft, String n="DEFAULT")
+  Hook(int t, std::string rs, SCM r, SCM f, int p, bool ft, std::string n="DEFAULT")
hunk ./source/BotInterp.H 86
+  typedef std::list<Hook *> HookList;
+  typedef std::map<int, HookList, std::less<int> > HookMap;
hunk ./source/BotInterp.H 91
-  std::map<int, std::list<Hook *>, std::less<int> > hooksMap;
+  int counter;
+
+  HookMap hooks;
hunk ./source/BotInterp.H 95
+
hunk ./source/BotInterp.H 97
-  int counter;
+  Utils::IndirectPred<Hook, std::less<Hook> > hook_sort_p;
+
hunk ./source/BotInterp.H 110
-  bool AddHook(int, SCM, SCM, int, bool, String);
-  bool RunHooks(int, String, SCM);
+  bool AddHook(int, SCM, SCM, int, bool, std::string);
+  bool RunHooks(int, std::string, SCM);
}