File indexing completed on 2026-04-09 07:49:29
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <cassert>
0032 #include <sstream>
0033 #include <iostream>
0034 #include <iomanip>
0035 #include <map>
0036 #include <vector>
0037 #include <functional>
0038
0039 #include "ssys.h"
0040 #include "NPX.h"
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 template<typename T>
0053 struct s_find
0054 {
0055 const T* q ;
0056 s_find(const T* q_) : q(q_) {} ;
0057 bool operator()(const std::pair<int, T*>& p){ return q == p.second ; }
0058 };
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 template<typename T, typename P>
0070 struct s_pool
0071 {
0072 typedef typename std::map<int, T*> POOL ;
0073 POOL pool ;
0074 const char* label ;
0075 int count ;
0076 int level ;
0077
0078 s_pool(const char* label);
0079
0080 int size() const ;
0081 int num_root() const ;
0082 bool all_root() const ;
0083
0084 T* get_root(int idx) const ;
0085
0086
0087
0088
0089
0090
0091 T* lookup(int pid) const ;
0092 T* getbyidx(int idx) const ;
0093
0094
0095 void find( std::vector<T*>& vec, std::function<bool(const T*)> predicate ) const ;
0096 void find_(std::vector<const T*>& vec, std::function<bool(const T*)> predicate ) const ;
0097
0098 std::string brief() const ;
0099 std::string desc() const ;
0100 void prepare_to_serialize();
0101
0102 int index(const T* q) const ;
0103 int add( T* o );
0104 int remove( T* o );
0105
0106 void serialize_( std::vector<P>& buf ) const ;
0107 void import_(const std::vector<P>& buf ) ;
0108
0109 template<typename S> NP* serialize() const ;
0110 template<typename S> void import(const NP* a) ;
0111
0112 static std::string Desc(const std::vector<P>& buf );
0113 };
0114
0115 template<typename T, typename P>
0116 inline s_pool<T,P>::s_pool(const char* label)
0117 :
0118 label(label ? strdup(label) : nullptr),
0119 count(0),
0120 level(ssys::getenvint("s_pool_level",0))
0121 {
0122 }
0123
0124 template<typename T, typename P>
0125 inline int s_pool<T,P>::size() const
0126 {
0127 return pool.size();
0128 }
0129 template<typename T, typename P>
0130 inline int s_pool<T,P>::num_root() const
0131 {
0132 int count_root = 0 ;
0133 typedef typename POOL::const_iterator IT ;
0134 for(IT it=pool.begin() ; it != pool.end() ; it++)
0135 {
0136 T* n = it->second ;
0137 if(n->is_root()) count_root += 1 ;
0138 }
0139 return count_root ;
0140 }
0141
0142 template<typename T, typename P>
0143 inline bool s_pool<T,P>::all_root() const
0144 {
0145 return size() == num_root() ;
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 template<typename T, typename P>
0162 inline T* s_pool<T,P>::get_root(int idx) const
0163 {
0164 T* root = nullptr ;
0165 int count_root = 0 ;
0166 typedef typename POOL::const_iterator IT ;
0167 for(IT it=pool.begin() ; it != pool.end() ; it++)
0168 {
0169 T* n = it->second ;
0170 if(n->is_root())
0171 {
0172 if( idx == count_root ) root = n ;
0173 count_root += 1 ;
0174 }
0175 }
0176 return root ;
0177 }
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 template<typename T, typename P>
0191 inline T* s_pool<T,P>::lookup(int pid) const
0192 {
0193 return pool.count(pid) == 1 ? pool.at(pid) : nullptr ;
0194 }
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212 template<typename T, typename P>
0213 inline T* s_pool<T,P>::getbyidx(int idx) const
0214 {
0215 int sz = int(pool.size()) ;
0216 #ifdef WITH_DANGEROUS_NEGATIVE_INDEXING
0217 if( idx < 0 ) idx += sz ;
0218 #endif
0219 if(idx < 0 || idx >= sz) return nullptr ;
0220
0221 typedef typename POOL::const_iterator IT ;
0222 IT it = pool.begin();
0223 std::advance(it, idx);
0224 return it->second ;
0225 }
0226
0227
0228
0229 template<typename T, typename P>
0230 inline void s_pool<T,P>::find(std::vector<T*>& vec, std::function<bool(const T*)> predicate ) const
0231 {
0232 typedef typename POOL::const_iterator IT ;
0233 for(IT it=pool.begin() ; it != pool.end() ; it++)
0234 {
0235 T* n = it->second ;
0236 if(predicate(n)) vec.push_back(n) ;
0237 }
0238 }
0239
0240
0241 template<typename T, typename P>
0242 inline void s_pool<T,P>::find_(std::vector<const T*>& vec, std::function<bool(const T*)> predicate ) const
0243 {
0244 typedef typename POOL::const_iterator IT ;
0245 for(IT it=pool.begin() ; it != pool.end() ; it++)
0246 {
0247 const T* n = it->second ;
0248 if(predicate(n)) vec.push_back(n) ;
0249 }
0250 }
0251
0252
0253
0254
0255 template<typename T, typename P>
0256 inline std::string s_pool<T,P>::brief() const
0257 {
0258 std::stringstream ss ;
0259 ss
0260 << "s_pool::brief "
0261 << " label " << ( label ? label : "-" )
0262 << " count " << count
0263 << " pool.size " << pool.size()
0264 << " num_root " << num_root()
0265 ;
0266 std::string str = ss.str();
0267 return str ;
0268 }
0269
0270 template<typename T, typename P>
0271 inline std::string s_pool<T,P>::desc() const
0272 {
0273 std::stringstream ss ;
0274 ss << "s_pool::desc "
0275 << " label " << ( label ? label : "-" )
0276 << " count " << count
0277 << " pool.size " << pool.size()
0278 << " num_root " << num_root()
0279 << std::endl
0280 ;
0281
0282 typedef typename POOL::const_iterator IT ;
0283 for(IT it=pool.begin() ; it != pool.end() ; it++)
0284 {
0285 int key = it->first ;
0286 T* n = it->second ;
0287 ss << std::setw(3) << key << " : " << n->desc() << std::endl ;
0288 }
0289 std::string str = ss.str();
0290 return str ;
0291 }
0292
0293 template<typename T, typename P>
0294 inline void s_pool<T,P>::prepare_to_serialize()
0295 {
0296 typedef typename POOL::iterator IT ;
0297 for(IT it=pool.begin() ; it != pool.end() ; it++)
0298 {
0299 T* n = it->second ;
0300 n->prepare_to_serialize();
0301 }
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 template<typename T, typename P>
0321 inline int s_pool<T, P>::index(const T* q) const
0322 {
0323 if( q == nullptr && level > 0) std::cerr
0324 << "s_pool::index got nullptr arg "
0325 << " pool.size " << pool.size()
0326 << std::endl
0327 ;
0328
0329 if( q == nullptr ) return -1 ;
0330
0331 s_find<T> find(q);
0332 size_t idx_ = std::distance( pool.begin(), std::find_if( pool.begin(), pool.end(), find ));
0333 int idx = idx_ < pool.size() ? idx_ : -1 ;
0334
0335 if( idx == -1 && level > 0) std::cerr
0336 << "s_pool::index failed to find non-nullptr "
0337 << " pool.size " << pool.size()
0338 << std::endl
0339 ;
0340
0341 return idx ;
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353 template<typename T, typename P>
0354 inline int s_pool<T, P>::add(T* o)
0355 {
0356 int pid = count ;
0357 pool[pid] = o ;
0358 if(level > 0) std::cerr
0359 << "s_pool::add "
0360 << ( label ? label : "-" )
0361 << " pid " << pid
0362 << std::endl
0363 ;
0364 count += 1 ;
0365 return pid ;
0366 }
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 template<typename T, typename P>
0379 inline int s_pool<T,P>::remove(T* o)
0380 {
0381 s_find<T> find(o);
0382 typename POOL::iterator it = std::find_if( pool.begin(), pool.end(), find ) ;
0383
0384 int pid = -1 ;
0385 if( it == pool.end() )
0386 {
0387 if(level > 0) std::cerr
0388 << "s_pool::remove FATAL "
0389 << ( label ? label : "-" )
0390 << " failed to find the object : already removed, double dtors ? or copy bug ? "
0391 << " o.pid " << ( o ? o->pid : -2 )
0392 << std::endl
0393 ;
0394 assert(0);
0395 }
0396 else
0397 {
0398 pid = it->first ;
0399 if(level > 0) std::cerr
0400 << "s_pool::remove "
0401 << ( label ? label : "-" )
0402 << " pid " << pid
0403 << std::endl
0404 ;
0405 pool.erase(it);
0406 }
0407 return pid ;
0408 }
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 template<typename T, typename P>
0421 inline void s_pool<T,P>::serialize_( std::vector<P>& buf ) const
0422 {
0423 buf.resize(pool.size());
0424 for(typename POOL::const_iterator it=pool.begin() ; it != pool.end() ; it++)
0425 {
0426 size_t idx = std::distance(pool.begin(), it );
0427 if(level > 1) std::cerr << "s_pool::serialize_ " << idx << std::endl ;
0428 T::Serialize( buf[idx], it->second );
0429 }
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441 template<typename T, typename P>
0442 inline void s_pool<T,P>::import_(const std::vector<P>& buf )
0443 {
0444 if(level > 0) std::cerr << "s_pool::import_ buf.size " << buf.size() << std::endl ;
0445 for(size_t idx=0 ; idx < buf.size() ; idx++) T::Import( &buf[idx], buf ) ;
0446 }
0447
0448 template<typename T, typename P>
0449 template<typename S>
0450 inline NP* s_pool<T,P>::serialize() const
0451 {
0452 std::vector<P> buf ;
0453 serialize_(buf);
0454 return NPX::ArrayFromVec_<S, P>(buf, P::ITEM) ;
0455 }
0456
0457 template<typename T, typename P>
0458 template<typename S>
0459 inline void s_pool<T,P>::import( const NP* a )
0460 {
0461 if(level > 0) std::cerr << "s_pool::import a.sstr " << ( a ? a->sstr() : "-" ) << std::endl ;
0462 std::vector<P> buf(a->shape[0]) ;
0463
0464 NPX::VecFromArray<P>(buf, a );
0465
0466 import_(buf);
0467 }
0468
0469 template<typename T, typename P>
0470 inline std::string s_pool<T,P>::Desc(const std::vector<P>& buf )
0471 {
0472 std::stringstream ss ;
0473 ss << "s_pool::Desc buf.size " << buf.size() << std::endl ;
0474 for(size_t idx=0 ; idx < buf.size() ; idx++) ss << " idx " << std::setw(3) << idx << " : " << buf[idx].desc() << std::endl ;
0475 std::string str = ss.str();
0476 return str ;
0477 }
0478
0479