39#include <unordered_map>
48template <
typename KeyT,
typename MappedT>
49using uomap_t = std::unordered_map<KeyT, MappedT>;
53template <
typename Type>
56 using pre_order_iterator =
typename graph_t::pre_order_iterator;
57 using sibling_iterator =
typename graph_t::sibling_iterator;
64 auto_lock_t l(singleton_t::get_mutex(), std::defer_lock);
69 if(!rhs.is_initialized())
74 PRINT_HERE(
"[%s]> nullptr to settings!", Type::get_label().c_str());
80 auto _copy_hash_ids = [&lhs, &rhs, _debug]() {
82 if(rhs.get_hash_ids() && lhs.get_hash_ids())
84 auto_lock_t _lk{ type_mutex<hash_map_t>(), std::defer_lock };
89 _debug,
"[%s]> merging %lu hash-ids into existing set of %lu hash-ids!",
90 Type::get_label().c_str(), (
unsigned long) rhs.get_hash_ids()->size(),
91 (
unsigned long) lhs.get_hash_ids()->size());
93 auto _hash_ids = *rhs.get_hash_ids();
94 for(
const auto& itr : _hash_ids)
96 if(lhs.m_hash_ids->find(itr.first) == lhs.m_hash_ids->end())
97 lhs.m_hash_ids->emplace(itr.first, itr.second);
101 if(rhs.get_hash_aliases() && lhs.get_hash_aliases())
103 auto_lock_t _lk{ type_mutex<hash_alias_map_t>(), std::defer_lock };
108 "[%s]> merging %lu hash-aliases into existing set of "
110 Type::get_label().c_str(),
111 (
unsigned long) rhs.get_hash_aliases()->size(),
112 (
unsigned long) lhs.get_hash_aliases()->size());
114 auto _hash_aliases = *rhs.get_hash_aliases();
115 for(
const auto& itr : _hash_aliases)
117 if(lhs.m_hash_aliases->find(itr.first) == lhs.m_hash_aliases->end())
118 lhs.m_hash_aliases->emplace(itr.first, itr.second);
124 if(rhs.is_initialized() && !lhs.is_initialized())
126 PRINT_HERE(
"[%s]> Warning! master is not initialized! Segmentation fault likely",
127 Type::get_label().c_str());
128 lhs.graph().insert_subgraph_after(lhs._data().head(), rhs.data().head());
129 lhs.graph().steal_resources(rhs.graph());
130 lhs.m_initialized = rhs.m_initialized;
131 lhs.m_finalized = rhs.m_finalized;
138 if(rhs.empty() || !rhs.data().has_head())
141 int64_t num_merged = 0;
142 auto inverse_insert = rhs.data().get_inverse_insert();
144 for(
auto entry : inverse_insert)
146 auto master_entry = lhs.data().find(
entry.second);
147 if(master_entry != lhs.data().end())
149 pre_order_iterator pitr(
entry.second);
151 if(rhs.graph().is_valid(pitr) && pitr)
154 _debug,
"[%s]> worker is merging %i records into %i records",
155 Type::get_label().c_str(), (
int) rhs.size(), (
int) lhs.size());
157 pre_order_iterator
pos = master_entry;
162 sibling_iterator other = pitr;
163 for(
auto sitr = other.begin(); sitr != other.end(); ++sitr)
165 pre_order_iterator pchild = sitr;
166 if(!pchild || pchild->data().get_is_invalid())
168 lhs.graph().append_child(
pos, pchild);
173 Type::get_label().c_str(), (
int) lhs.size());
181 int64_t merge_size =
static_cast<int64_t
>(inverse_insert.size());
182 if(num_merged != merge_size)
184 int64_t diff = merge_size - num_merged;
185 std::stringstream ss;
186 ss <<
"Testing error! Missing " << diff <<
" merge points. The worker thread "
187 <<
"contained " << merge_size <<
" bookmarks but only merged " << num_merged
192#if defined(TIMEMORY_TESTING) || defined(TIMEMORY_INTERNAL_TESTING)
200 Type::get_label().c_str());
201 pre_order_iterator _nitr(rhs.data().head());
203 if(!lhs.graph().is_valid(_nitr))
204 _nitr = pre_order_iterator(rhs.data().head());
205 lhs.graph().append_child(lhs._data().head(), _nitr);
209 Type::get_label().c_str());
211 lhs.graph().steal_resources(rhs.graph());
217template <
typename Type>
220 using result_node =
typename result_type::value_type;
224 dst.reserve(dst.size() + src.size());
225 }
catch(std::bad_alloc& e)
227 std::cerr <<
"Warning! Running out of memory is probable! " << e.what()
233 using merge_hash_map_t =
239 merge_hash_map_t _hash_table{};
244 auto _add_entry = [&_hash_table](
const result_node& _obj, int64_t _idx) {
245 _hash_table[_obj.depth()][_obj.hash()][_obj.rolling_hash()][_obj.prefix()] = _idx;
251 auto _get_index = [&](
const result_node& _lhs) -> int64_t {
252 auto& _tbl = _hash_table[_lhs.depth()][_lhs.hash()][_lhs.rolling_hash()];
253 auto itr = _tbl.find(_lhs.prefix());
254 if(itr != _tbl.end())
262 for(
size_t i = 0; i < dst.size(); ++i)
263 _add_entry(dst.at(i),
static_cast<int64_t
>(i));
274 if(_debug || _verbose > 0)
276 fprintf(stderr,
"Merging %lu new records into %lu existing records\n",
277 (
unsigned long) src.size(), (
unsigned long) dst.size());
282 if(_debug || _verbose > 3)
284 fprintf(stderr,
"Checking %lu of %lu...", (
unsigned long) cnt++,
285 (
unsigned long) src.size());
288 auto idx = _get_index(itr);
291 if(_debug || _verbose > 3)
292 fprintf(stderr,
"new entry\n");
293 _add_entry(itr,
static_cast<int64_t
>(dst.size()));
294 dst.emplace_back(std::move(itr));
299 if(_debug || _verbose > 3)
300 fprintf(stderr,
"duplicate\n");
301 auto& citr = dst.at(idx);
302 citr.data() += itr.data();
303 citr.data().plus(itr.data());
304 citr.stats() += itr.stats();
308 if(_debug || _verbose > 0)
310 fprintf(stderr,
"Merged %lu duplicates into %lu records\n", (
unsigned long) ndup,
311 (
unsigned long) dst.size());
320template <
typename Type>
321template <
typename Tp>
334 for(
auto& itr :
_ret.get_children())
335 *itr = (*this)(*itr);
338 children_type _children{};
339 for(
auto& itr :
_ret.get_children())
342 for(
auto& citr : _children)
351 _children.emplace_back(itr);
356 _ret.get_children() = _children;
362template <
typename Type>
363template <
typename Tp>
372template <
typename Type>
373template <
typename Tp>
374std::vector<basic_tree<Tp>>
378 for(
auto& itr :
_ret)
385template <
typename Type>
386template <
typename Tp>
387std::vector<basic_tree<Tp>>
392 using basic_vec_t = std::vector<basic_t>;
393 using basic_map_t = std::map<size_t, basic_t>;
394 using basic_bool_t = std::vector<bool>;
396 auto _p = basic_map_t{};
397 auto _ul = basic_map_t{};
398 auto _ur = basic_map_t{};
399 auto _bl = basic_bool_t(_lhs.size(),
false);
400 auto _br = basic_bool_t(_rhs.size(),
false);
401 for(
size_t i = 0; i < _lhs.size(); ++i)
403 const auto& _l = _lhs.at(i);
405 for(
size_t j = 0; j < _rhs.size(); ++j)
407 const auto& _r = _rhs.at(j);
412 if(_p.find(i) == _p.end())
414 _p[i] += (*this)(_r);
419 _ul[i] = (*
this)(_l);
422 for(
size_t j = 0; j < _rhs.size(); ++j)
425 const auto& _r = _rhs.at(j);
427 _ur[j] = (*
this)(_r);
431 auto _ret = basic_vec_t{};
432 auto n = std::max<size_t>(_lhs.size(), _rhs.size());
434 for(
size_t i = 0; i < n; ++i)
436 auto _append = [&](
auto& _obj) {
437 auto itr = _obj.find(i);
438 if(itr != _obj.end())
439 _ret.emplace_back(itr->second);
447 return (*
this)(
_ret);
452template <
typename Type>
453template <
typename Tp>
454std::vector<basic_tree<Tp>>
461 if(_root >= _bt.size())
463 auto _ret = _bt.at(_root);
464 for(
size_t i = 0; i <
_ret.size(); ++i)
471 return (*
this)(
_ret);
518template <
typename Type>
524 auto_lock_t l(singleton_t::get_mutex(), std::defer_lock);
528 for(
const auto& itr : *rhs.get_hash_ids())
530 if(lhs.m_hash_ids->find(itr.first) == lhs.m_hash_ids->end())
531 (*lhs.m_hash_ids)[itr.first] = itr.second;
533 for(
const auto& itr : (*rhs.get_hash_aliases()))
535 if(lhs.m_hash_aliases->find(itr.first) == lhs.m_hash_aliases->end())
536 (*lhs.m_hash_aliases)[itr.first] = itr.second;
const hash_alias_ptr_t hash_value_t std::string *& _ret
std::unordered_map< KeyT, MappedT > uomap_t
std::unique_lock< mutex_t > auto_lock_t
Unique lock type around mutex_t.
char argparse::argument_parser tim::settings * _settings
The declaration for the types for operations without definitions.
Include the macros for operations.
Declare the operations types.
Basic hierarchical tree implementation. Expects population from tim::graph.
auto & get_children()
return the array of child nodes
std::vector< child_pointer > children_type
impl::storage< Type, has_data > storage_type
typename storage_type::result_array_t result_type
impl::storage< Type, has_data > storage_type
static settings * instance()
#define CONDITIONAL_PRINT_HERE(CONDITION,...)
#define TIMEMORY_EXCEPTION(...)