diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index 2c376847e1..c170391844 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -156,7 +156,6 @@ set(IVOC_FILE_LIST grglyph.cpp grmanip.cpp hocmark.cpp - htlist.cpp idraw.cpp ivoc.cpp ivocmain.cpp diff --git a/src/ivoc/htlist.cpp b/src/ivoc/htlist.cpp deleted file mode 100644 index 953f8895b8..0000000000 --- a/src/ivoc/htlist.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include <../../nrnconf.h> -#endif -/* -Based on Unidraw UList but UList changed to HTList (head tail list) -for fast insertion, deletion, iteration -*/ - -/* - * Copyright (c) 1990, 1991 Stanford University - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Stanford not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Stanford makes no representations about - * the suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. - * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * HTList implementation. - */ - -#include -#include -#include - -/*****************************************************************************/ - -HTList::HTList(void* p) { - _next = this; - _prev = this; - _object = p; -} - -HTList::~HTList() { - HTList* next = _next; - if (next != this && next != NULL) { - Remove(this); - delete next; - } -} - -void HTList::Append(HTList* e) { - _prev->_next = e; - e->_prev = _prev; - e->_next = this; - _prev = e; -} - -void HTList::Prepend(HTList* e) { - _next->_prev = e; - e->_prev = this; - e->_next = _next; - _next = e; -} - -void HTList::Remove(HTList* e) { - e->_prev->_next = e->_next; - e->_next->_prev = e->_prev; - e->_prev = e->_next = NULL; -} - -void HTList::Remove() { - if (_prev) { - _prev->_next = _next; - } - if (_next) { - _next->_prev = _prev; - } - _prev = _next = NULL; -} -void HTList::RemoveAll() { - while (!IsEmpty()) { - Remove(First()); - } -} -void HTList::Delete(void* p) { - HTList* e; - - e = Find(p); - if (e != NULL) { - Remove(e); - delete e; - } -} - -HTList* HTList::Find(void* p) { - HTList* e; - - for (e = _next; e != this; e = e->_next) { - if (e->_object == p) { - return e; - } - } - return NULL; -} - -HTList* HTList::operator[](int count) { - HTList* pos = First(); - int i; - - for (i = 1; i < count && pos != End(); ++i) { - pos = pos->Next(); - } - if (i == count) { - return pos; - } - return NULL; -} diff --git a/src/ivoc/htlist.h b/src/ivoc/htlist.h deleted file mode 100644 index cab97c944f..0000000000 --- a/src/ivoc/htlist.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -from Unidraw but UList changed to HTList (head tail list) -for fast insertion, deletion, iteration -*/ - -/* - * Copyright (c) 1990, 1991 Stanford University - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Stanford not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Stanford makes no representations about - * the suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. - * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * UList - list object. - */ - -#pragma once - -class HTList { - public: - HTList(void* = NULL); - virtual ~HTList(); - - bool IsEmpty(); - void Append(HTList*); - void Prepend(HTList*); - void Remove(HTList*); - void Remove(); - void RemoveAll(); - void Delete(void*); - HTList* Find(void*); - HTList* First(); - HTList* Last(); - HTList* End(); - HTList* Next(); - HTList* Prev(); - - void* vptr(); - void* operator()(); - HTList* operator[](int count); - - protected: - void* _object; - HTList* _next; - HTList* _prev; -}; - -inline bool HTList::IsEmpty() { - return _next == this; -} -inline HTList* HTList::First() { - return _next; -} -inline HTList* HTList::Last() { - return _prev; -} -inline HTList* HTList::End() { - return this; -} -inline HTList* HTList::Next() { - return _next; -} -inline HTList* HTList::Prev() { - return _prev; -} -inline void* HTList::operator()() { - return _object; -} -inline void* HTList::vptr() { - return _object; -} diff --git a/src/nrncvode/cvodeobj.cpp b/src/nrncvode/cvodeobj.cpp index 89b2ca3e58..fc4da90ca8 100644 --- a/src/nrncvode/cvodeobj.cpp +++ b/src/nrncvode/cvodeobj.cpp @@ -23,7 +23,6 @@ extern int hoc_return_type_code; #include "nrnpy.h" #include "tqueue.hpp" #include "mymath.h" -#include "htlist.h" #include #if NRN_ENABLE_THREADS diff --git a/src/nrncvode/cvodeobj.h b/src/nrncvode/cvodeobj.h index f4f0d26bd1..eb8b52a665 100644 --- a/src/nrncvode/cvodeobj.h +++ b/src/nrncvode/cvodeobj.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "nrnmpi.h" #include "nrnneosm.h" //#include "shared/nvector_serial.h" @@ -16,7 +18,6 @@ struct BAMech; struct NrnThread; class PlayRecord; class STEList; -class HTList; namespace neuron { struct model_sorted_token; } @@ -72,7 +73,7 @@ class CvodeThreadData { Node** v_node_; Node** v_parent_; PreSynList* psl_th_; // with a threshold - HTList* watch_list_; + std::list* watch_list_; std::vector> pv_, pvdot_; int nvoffset_; // beginning of this threads states int nvsize_; // total number of states for this thread diff --git a/src/nrncvode/netcon.h b/src/nrncvode/netcon.h index 55b047a2b6..5390f1e552 100644 --- a/src/nrncvode/netcon.h +++ b/src/nrncvode/netcon.h @@ -2,12 +2,12 @@ #undef check -#include "htlist.h" #include "neuron/container/data_handle.hpp" #include "nrnmpi.h" #include "nrnneosm.h" #include "pool.hpp" #include "tqitem.hpp" +#include "utils/signal.hpp" #include @@ -212,7 +212,7 @@ class ConditionEvent: public DiscreteEvent { static unsigned long deliver_qthresh_; }; -class WatchCondition: public ConditionEvent, public HTList { +class WatchCondition: public ConditionEvent { public: WatchCondition(Point_process*, double (*)(Point_process*)); virtual ~WatchCondition(); @@ -242,16 +242,17 @@ class WatchCondition: public ConditionEvent, public HTList { static unsigned long watch_send_; static unsigned long watch_deliver_; + + signal_ unregister; }; class STECondition: public WatchCondition { public: STECondition(Point_process*, double (*)(Point_process*) = NULL); - virtual ~STECondition(); - virtual void deliver(double, NetCvode*, NrnThread*); - virtual void pgvts_deliver(double t, NetCvode*); - virtual double value(); - virtual NrnThread* thread(); + void deliver(double, NetCvode*, NrnThread*) override; + void pgvts_deliver(double t, NetCvode*) override; + double value() override; + NrnThread* thread() override; STETransition* stet_; }; diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index 0110299653..94df2cdf8b 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -26,7 +26,6 @@ #include "vrecitem.h" #include "oclist.h" #define PROFILE 0 -#include "htlist.h" #include "ivocvect.h" #include "netcon.h" #include "netcvode.h" @@ -1265,7 +1264,7 @@ CvodeThreadData::~CvodeThreadData() { delete[] no_cap_child_; } if (watch_list_) { - watch_list_->RemoveAll(); + watch_list_->clear(); delete watch_list_; } } @@ -2326,7 +2325,7 @@ void _nrn_watch_activate(Datum* d, } if (r == 0) { for (auto wc1: *wl) { - wc1->Remove(); + wc1->unregister.send(wc1); if (wc1->qthresh_) { // is it on the queue? net_cvode_instance->remove_event(wc1->qthresh_, PP2NT(pnt)->id); wc1->qthresh_ = nullptr; @@ -2425,8 +2424,8 @@ void _nrn_watch_allocate(Datum* d, void nrn_watch_clear() { assert(net_cvode_instance->wl_list_.size() == (size_t) nrn_nthread); for (auto& htlists_of_thread: net_cvode_instance->wl_list_) { - for (HTList* wl: htlists_of_thread) { - wl->RemoveAll(); + for (auto* wl: htlists_of_thread) { + wl->clear(); } } // not necessary to empty the WatchList in the Point_process dparam array @@ -2444,7 +2443,7 @@ void _nrn_free_watch(Datum* d, int offset, int n) { } for (i = offset + 1; i < nn; ++i) { if (auto* wc = d[i].get(); wc) { - wc->Remove(); + wc->unregister.send(wc); delete wc; d[i] = nullptr; } @@ -2776,7 +2775,7 @@ void NetCvode::init_events() { if (gcv_) { for (int j = 0; j < nrn_nthread; ++j) { if (gcv_->ctd_[j].watch_list_) { - gcv_->ctd_[j].watch_list_->RemoveAll(); + gcv_->ctd_[j].watch_list_->clear(); } } } else { @@ -2784,7 +2783,7 @@ void NetCvode::init_events() { NetCvodeThreadData& d = p[j]; for (i = 0; i < d.nlcv_; ++i) { if (d.lcv_[i].ctd_[0].watch_list_) { - d.lcv_[i].ctd_[0].watch_list_->RemoveAll(); + d.lcv_[i].ctd_[0].watch_list_->clear(); } } } @@ -5240,27 +5239,19 @@ void ConditionEvent::abandon_statistics(Cvode* cv) { #endif } -WatchCondition::WatchCondition(Point_process* pnt, double (*c)(Point_process*)) - : HTList(nullptr) { +WatchCondition::WatchCondition(Point_process* pnt, double (*c)(Point_process*)) { pnt_ = pnt; c_ = c; watch_index_ = 0; // For transfer, will be a small positive integer. } WatchCondition::~WatchCondition() { - // printf("~WatchCondition\n"); - Remove(); + unregister.send(this); } // A WatchCondition but with different deliver STECondition::STECondition(Point_process* pnt, double (*c)(Point_process*)) - : WatchCondition(pnt, c) { - // printf("STECondition\n"); -} - -STECondition::~STECondition() { - // printf("~STECondition\n"); -} + : WatchCondition(pnt, c) {} void WatchCondition::activate(double flag) { Cvode* cv = NULL; @@ -5279,13 +5270,19 @@ void WatchCondition::activate(double flag) { } assert(cv); id = (cv->nctd_ > 1) ? thread()->id : 0; - HTList*& wl = cv->ctd_[id].watch_list_; + auto*& wl = cv->ctd_[id].watch_list_; if (!wl) { - wl = new HTList(nullptr); + wl = new std::list(); net_cvode_instance->wl_list_[id].push_back(wl); } - Remove(); - wl->Append(this); + unregister.send(this); + wl->push_back(this); + unregister.connect([&](WatchCondition* wc) { + auto it = std::find(wl->begin(), wl->end(), wc); + if (it != wl->end()) { + wl->erase(it); + } + }); } void WatchCondition::asf_err() { @@ -5354,7 +5351,7 @@ void STETransition::deactivate() { net_cvode_instance->remove_event(stec_->qthresh_, stec_->thread()->id); stec_->qthresh_ = nullptr; } - stec_->Remove(); + stec_->unregister.send(stec_.get()); } void STECondition::deliver(double tt, NetCvode* ns, NrnThread* nt) { @@ -5458,9 +5455,8 @@ void Cvode::evaluate_conditions(NrnThread* nt) { } } if (z.watch_list_) { - for (HTList* item = z.watch_list_->First(); item != z.watch_list_->End(); - item = item->Next()) { - ((WatchCondition*) item)->condition(this); + for (auto wc: *z.watch_list_) { + wc->condition(this); } } } @@ -5487,9 +5483,8 @@ void Cvode::check_deliver(NrnThread* nt) { } } if (z.watch_list_) { - for (HTList* item = z.watch_list_->First(); item != z.watch_list_->End(); - item = item->Next()) { - ((WatchCondition*) item)->check(nt, nt->_t); + for (auto wc: *z.watch_list_) { + wc->check(nt, nt->_t); } } } @@ -5901,9 +5896,8 @@ void NetCvode::check_thresh(NrnThread* nt) { // for default method } } - for (HTList* wl: wl_list_[nt->id]) { - for (HTList* item = wl->First(); item != wl->End(); item = item->Next()) { - WatchCondition* wc = (WatchCondition*) item; + for (const auto* wl: wl_list_[nt->id]) { + for (auto wc: *wl) { wc->check(nt, nt->_t); } } @@ -5919,9 +5913,8 @@ void nrn2core_transfer_WATCH(void (*cb)(int, int, int, int, int)) { // should be revisited for possible simplification since wl_list now // segregated by threads. for (auto& htlists_of_thread: net_cvode_instance->wl_list_) { - for (HTList* wl: htlists_of_thread) { - for (HTList* item = wl->First(); item != wl->End(); item = item->Next()) { - WatchCondition* wc = (WatchCondition*) item; + for (const auto* wl: htlists_of_thread) { + for (auto wc: *wl) { nrn2core_transfer_WatchCondition(wc, cb); } } diff --git a/src/nrncvode/netcvode.h b/src/nrncvode/netcvode.h index 8eb047e6d4..93b7311756 100644 --- a/src/nrncvode/netcvode.h +++ b/src/nrncvode/netcvode.h @@ -24,12 +24,11 @@ struct hoc_Item; class PlayRecord; class IvocVect; struct BAMechList; -class HTList; // nrn_nthread vectors of HTList* for fixed step method // Thread segregated HTList* of all the CVode.CvodeThreadData.HTList* // Interior vector needed because of the chance of local variable time step. // Practically it will always have length <= 1. -using HTListList = std::vector>; +using HTListList = std::vector*>>; class NetCvode; class MaxStateItem; typedef std::unordered_map MaxStateTable; diff --git a/src/utils/signal.hpp b/src/utils/signal.hpp new file mode 100644 index 0000000000..4215e44e05 --- /dev/null +++ b/src/utils/signal.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +template +class signal_ { + public: + using key_type = unsigned; + + template + key_type connect(F f) { + ++counter; + functors[counter] = f; + return counter; + } + + void disconnect(unsigned i) { + auto it = functors.find(i); + if (it != functors.end()) { + functors.erase(it); + } + } + + void send(Args... args) const { + for (const auto& [i, f]: functors) { + std::invoke(f, args...); + } + } + + private: + key_type counter = 0; + std::unordered_map> functors; +};