[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::iterator it = hooksMap[hooktype].begin(); - std::list::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::reverse_iterator it = hooksMap[hooktype].rbegin(); - std::list::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 (&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 (&wd), + (scm_t_catch_handler) Interp::EmptyHandler, 0); + if (!fallthru_p) + break; + } hunk ./source/BotInterp.C 192 - } - + hunk ./source/BotInterp.H 30 -#include -#include hunk ./source/BotInterp.H 31 +#include +#include +#include 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 HookList; + typedef std::map > HookMap; hunk ./source/BotInterp.H 91 - std::map, std::less > hooksMap; + int counter; + + HookMap hooks; hunk ./source/BotInterp.H 95 + hunk ./source/BotInterp.H 97 - int counter; + Utils::IndirectPred > 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); }