13 #ifndef FOXXLL_MNG_BLOCK_SCHEDULER_HEADER 14 #define FOXXLL_MNG_BLOCK_SCHEDULER_HEADER 50 template <
typename ValueType,
size_t BlockSize>
53 constexpr
static bool debug =
false;
82 : external_data() , internal_data(0), dirty(false), reference_count(0) { }
88 {
return (internal_data !=
nullptr); }
96 {
return external_data.valid(); }
104 {
return reference_count > 0; }
119 return dirty = make_dirty ||
dirty;
163 return internal_data->
read(external_data, on_cmpl);
182 return internal_data->
write(external_data, on_cmpl);
197 internal_data = iblock;
232 external_data = eblock;
246 template <
typename ValueType,
size_t BlockSize>
249 template <
class SwappableBlockType>
252 template <
class SwappableBlockType>
264 template <
class SwappableBlockType>
267 constexpr
static bool debug =
false;
300 op_extract_external_block
311 : op(op), id(id), time(time) { }
330 std::priority_queue<swappable_block_identifier_type, std::vector<swappable_block_identifier_type>,
339 if (! free_internal_blocks.empty())
343 free_internal_blocks.pop();
346 else if (remaining_internal_blocks > 0)
349 size_t num_blocks =
std::min(max_internal_blocks_alloc_at_once, remaining_internal_blocks);
350 remaining_internal_blocks -= num_blocks;
352 internal_blocks_blocks.push(iblocks);
353 for (
size_t i = num_blocks - 1; i > 0; --i)
354 free_internal_blocks.push(iblocks + i);
366 { free_internal_blocks.push(iblock); }
373 remaining_internal_blocks(max_internal_blocks),
388 size_t num_freed_internal_blocks = 0;
389 if (free_swappable_blocks.size() != swappable_blocks.size())
392 TLX_LOG1 <<
"not all swappable_blocks are free, those not acquired will be deinitialized";
394 for (
typename std::vector<SwappableBlockType>::iterator it = swappable_blocks.begin();
395 it != swappable_blocks.end(); ++it)
397 if (! it->is_acquired() && it->deinitialize())
399 num_freed_internal_blocks++;
402 if (int64_t nlost = static_cast<int64_t>(max_internal_blocks - remaining_internal_blocks)
403 -
static_cast<int64_t
>(free_internal_blocks.size() + num_freed_internal_blocks)) {
404 TLX_LOG1 << nlost <<
" internal_blocks are lost. They will get deallocated.";
406 while (! internal_blocks_blocks.empty())
408 delete[] internal_blocks_blocks.top();
409 internal_blocks_blocks.pop();
418 {
return algo->
acquire(sbid, uninitialized); }
425 { algo->
release(sbid, dirty); }
461 {
return swappable_blocks[sbid].get_internal_block(); }
468 if (free_swappable_blocks.empty())
471 sbid = swappable_blocks.size();
472 swappable_blocks.resize(sbid + 1);
478 sbid = free_swappable_blocks.top();
479 free_swappable_blocks.pop();
489 free_swappable_blocks.push(sbid);
502 assert(&new_algo->
bs ==
this);
521 std::vector<request_ptr> requests;
525 request_ptr rq = swappable_blocks[sbid].clean_async();
527 requests.push_back(rq);
530 for (
typename std::vector<request_ptr>::reverse_iterator it = requests.rbegin();
531 it != requests.rend(); ++it)
538 template <
class SwappableBlockType>
542 template <
class SwappableBlockType>
575 swappable_blocks(bs.swappable_blocks)
580 swappable_blocks(bs.swappable_blocks)
590 virtual bool evictable_blocks_empty() = 0;
601 {
return swappable_blocks[sbid].is_initialized(); }
607 {
return prediction_sequence; }
611 template <
class SwappableBlockType>
621 using block_scheduler_algorithm_type::bs;
622 using block_scheduler_algorithm_type::swappable_blocks;
623 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
624 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
625 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
636 assert(! evictable_blocks.
empty());
637 return swappable_blocks[evictable_blocks.
pop()].detach_internal_block();
641 { return_free_internal_block_to_block_scheduler(iblock); }
645 if (get_algorithm_from_block_scheduler())
646 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
647 evictable_blocks.
insert(get_algorithm_from_block_scheduler()->evictable_blocks_pop());
661 if (! evictable_blocks.
empty())
662 TLX_LOG1 <<
"Destructing block_scheduler_algorithm_online that still holds evictable blocks. They get deinitialized.";
663 while (! evictable_blocks.
empty())
665 SwappableBlockType& sblock = swappable_blocks[evictable_blocks.
pop()];
667 return_free_internal_block(iblock);
672 {
return evictable_blocks.
empty(); }
675 {
return evictable_blocks.
pop(); }
679 SwappableBlockType& sblock = swappable_blocks[sbid];
685 if (sblock.is_internal())
687 if (! sblock.is_acquired())
689 evictable_blocks.
erase(sbid);
692 else if (sblock.is_initialized())
696 sblock.attach_internal_block(get_free_internal_block());
706 sblock.attach_internal_block(get_free_internal_block());
710 sblock.fill_default();
712 return sblock.get_internal_block();
717 SwappableBlockType& sblock = swappable_blocks[sbid];
718 sblock.make_dirty_if(dirty);
720 if (! sblock.is_acquired())
722 if (sblock.is_dirty() || sblock.is_external())
724 evictable_blocks.
insert(sbid);
727 return_free_internal_block(sblock.detach_internal_block());
733 SwappableBlockType& sblock = swappable_blocks[sbid];
734 if (sblock.is_evictable())
735 evictable_blocks.
erase(sbid);
737 return_free_internal_block(iblock);
742 SwappableBlockType& sblock = swappable_blocks[sbid];
743 sblock.initialize(eblock);
748 SwappableBlockType& sblock = swappable_blocks[sbid];
749 if (sblock.is_evictable())
750 evictable_blocks.
erase(sbid);
751 if (sblock.is_internal())
752 return_free_internal_block(sblock.detach_internal_block());
753 return sblock.extract_external_block();
758 template <
class SwappableBlockType>
770 using block_scheduler_algorithm_type::bs;
771 using block_scheduler_algorithm_type::prediction_sequence;
772 using block_scheduler_algorithm_type::swappable_blocks;
773 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
774 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
775 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
785 { return_free_internal_block_to_block_scheduler(iblock); }
789 if (get_algorithm_from_block_scheduler())
790 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
791 evictable_blocks.push(get_algorithm_from_block_scheduler()->evictable_blocks_pop());
800 last_op_release(false),
801 reference_counts(swappable_blocks.size())
807 last_op_release(false),
808 reference_counts(swappable_blocks.size())
813 if (! evictable_blocks.empty())
814 TLX_LOG1 <<
"Destructing block_scheduler_algorithm_record_prediction_sequence that still holds evictable blocks. They get deinitialized.";
815 while (! evictable_blocks.empty())
817 SwappableBlockType& sblock = swappable_blocks[evictable_blocks.top()];
819 return_free_internal_block(iblock);
820 evictable_blocks.pop();
825 {
return evictable_blocks.empty(); }
830 evictable_blocks.pop();
836 ++reference_counts[sbid];
837 last_op_release =
false;
839 prediction_sequence.push_back(
843 prediction_sequence.push_back(
851 --reference_counts[sbid] +=
dirty;
852 time_count += ! last_op_release;
853 last_op_release =
true;
855 prediction_sequence.push_back(
859 prediction_sequence.push_back(
866 reference_counts[sbid] =
false;
867 prediction_sequence.push_back(
874 reference_counts[sbid] =
true;
875 prediction_sequence.push_back(
882 reference_counts[sbid] =
false;
883 prediction_sequence.push_back(
891 reference_counts.resize(size, 0);
896 return reference_counts[sbid] > 0;
907 template <
class SwappableBlockType>
919 using block_scheduler_algorithm_type::bs;
920 using block_scheduler_algorithm_type::swappable_blocks;
921 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
922 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
923 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
930 priority(
const SwappableBlockType& sblock,
const std::pair<bool, time_type>& t)
936 p = size_t(t.second) << 2;
938 p |= size_t(! sblock.is_dirty()) << 1;
940 p |= size_t(sblock.has_external_block()) << 0;
947 p |= size_t(t.second) << 0;
953 {
return p > right.
p; }
974 assert(! evictable_blocks.
empty());
975 return swappable_blocks[evictable_blocks.
pop()].detach_internal_block();
979 { return_free_internal_block_to_block_scheduler(iblock); }
983 std::vector<std::pair<bool, time_type> >
984 blocks_next_acquire(swappable_blocks.size(), std::make_pair(
false, 1));
989 for (
typename prediction_sequence_type::const_reverse_iterator it = ps.rbegin(); it != ps.rend(); ++it)
993 case (block_scheduler_type::op_acquire):
994 case (block_scheduler_type::op_acquire_uninitialized):
995 blocks_next_acquire[it->id] = std::make_pair(
true, it->time);
997 case (block_scheduler_type::op_release):
998 case (block_scheduler_type::op_release_dirty):
999 next_use.push_front(blocks_next_acquire[it->id]);
1001 case (block_scheduler_type::op_deinitialize):
1002 blocks_next_acquire[it->id] = std::make_pair(
false, 0);
1004 case (block_scheduler_type::op_initialize):
1005 blocks_next_acquire[it->id] = std::make_pair(
false, 3);
1007 case (block_scheduler_type::op_extract_external_block):
1008 blocks_next_acquire[it->id] = std::make_pair(
false, 2);
1013 if (get_algorithm_from_block_scheduler())
1015 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
1019 evictable_blocks.
insert(sbid,
priority(swappable_blocks[sbid], blocks_next_acquire[sbid]));
1027 { init(get_algorithm_from_block_scheduler()); }
1036 if (! evictable_blocks.
empty())
1037 TLX_LOG1 <<
"Destructing block_scheduler_algorithm_offline_lfd that still holds evictable blocks. They get deinitialized.";
1038 while (! evictable_blocks.
empty())
1040 SwappableBlockType& sblock = swappable_blocks[evictable_blocks.
pop()];
1042 return_free_internal_block(iblock);
1047 {
return evictable_blocks.
empty(); }
1050 {
return evictable_blocks.
pop(); }
1054 SwappableBlockType& sblock = swappable_blocks[sbid];
1060 if (sblock.is_internal())
1062 if (! sblock.is_acquired())
1064 evictable_blocks.
erase(sbid);
1067 else if (sblock.is_initialized())
1071 sblock.attach_internal_block(get_free_internal_block());
1072 if (! uninitialized)
1081 sblock.attach_internal_block(get_free_internal_block());
1084 if (! uninitialized)
1085 sblock.fill_default();
1087 return sblock.get_internal_block();
1092 if (next_use.empty())
1094 TLX_LOG1 <<
"block_scheduler_algorithm_offline_lfd got release-request but prediction sequence ended. Switching to block_scheduler_algorithm_online.";
1098 old_algo = bs.switch_algorithm_to(new_algo);
1100 new_algo->
release(sbid, dirty);
1105 SwappableBlockType& sblock = swappable_blocks[sbid];
1106 sblock.make_dirty_if(dirty);
1108 if (! sblock.is_acquired())
1110 if (sblock.is_dirty() || sblock.is_external())
1112 evictable_blocks.
insert(sbid,
priority(swappable_blocks[sbid], next_use.front()));
1115 return_free_internal_block(sblock.detach_internal_block());
1117 next_use.pop_front();
1122 SwappableBlockType& sblock = swappable_blocks[sbid];
1123 if (sblock.is_evictable())
1124 evictable_blocks.
erase(sbid);
1126 return_free_internal_block(iblock);
1131 SwappableBlockType& sblock = swappable_blocks[sbid];
1132 sblock.initialize(eblock);
1137 SwappableBlockType& sblock = swappable_blocks[sbid];
1138 if (sblock.is_evictable())
1139 evictable_blocks.
erase(sbid);
1140 if (sblock.is_internal())
1141 return_free_internal_block(sblock.detach_internal_block());
1142 return sblock.extract_external_block();
1148 template <
class SwappableBlockType>
1172 using block_scheduler_algorithm_type::bs;
1173 using block_scheduler_algorithm_type::swappable_blocks;
1174 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
1175 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
1176 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
1177 using block_scheduler_algorithm_type::prediction_sequence;
1188 : write_done_soon(false), shall_read(false), block_to_start_read(),
1189 taker(), write_req(nullptr) { }
1197 : wrr(write_read_req) { }
1210 std::pair<bool, swappable_block_identifier_type>
giver;
1215 : reserved_iblock(0),
1219 { operations.push_front(op); }
1240 SwappableBlockType& sblock = swappable_blocks[sbid];
1245 bool t = write_scheduled_blocks.insert(std::make_pair(sbid, wrr)).second;
1265 writing_block->second->shall_read =
false;
1267 if (! writing_block->second->write_done_soon)
1272 wait_on_write(writing_block);
1274 if (taker.second.read_req.valid())
1291 if (it != write_scheduled_blocks.end())
1295 if (it->second->shall_read)
1297 if (try_interrupt_read(it))
1300 std::swap(other_block_to_read->second.giver, block_to_read->second.giver);
1301 if (other_block_to_read->second.giver.first)
1304 if (it != write_scheduled_blocks.end())
1305 it->second->taker = other_block_to_read;
1307 other_block_to_read->second.giver.first =
false;
1309 if (block_to_read->second.giver.first)
1312 if (it != write_scheduled_blocks.end())
1313 it->second->taker = block_to_read;
1315 block_to_read->second.giver.first =
false;
1318 internal_block_type* tmp_iblock = swappable_blocks[block_to_read->first].detach_internal_block();
1319 swappable_blocks[block_to_read->first].attach_internal_block(
1320 swappable_blocks[other_block_to_read->first].detach_internal_block()
1322 swappable_blocks[other_block_to_read->first].attach_internal_block(tmp_iblock);
1325 schedule_read(other_block_to_read);
1333 std::swap(other_block_to_read->second.giver, block_to_read->second.giver);
1334 if (other_block_to_read->second.giver.first)
1337 if (it != write_scheduled_blocks.end())
1338 it->second->taker = other_block_to_read;
1340 other_block_to_read->second.giver.first =
false;
1342 if (block_to_read->second.giver.first)
1345 if (it != write_scheduled_blocks.end())
1346 it->second->taker = block_to_read;
1348 block_to_read->second.giver.first =
false;
1351 internal_block_type* tmp_iblock = swappable_blocks[block_to_read->first].detach_internal_block();
1352 swappable_blocks[block_to_read->first].attach_internal_block(
1353 other_block_to_read->second.reserved_iblock
1355 other_block_to_read->second.reserved_iblock = tmp_iblock;
1362 if (block_to_read->second.giver.first)
1365 if (writing_block != write_scheduled_blocks.end())
1369 writing_block->second->block_to_start_read = swappable_blocks.begin() + block_to_read->first;
1370 writing_block->second->taker = block_to_read;
1371 writing_block->second->shall_read =
true;
1373 if (writing_block->second->write_done_soon)
1377 wait_on_write(writing_block);
1378 block_to_read->second.giver.first =
false;
1379 if (block_to_read->second.read_req.valid())
1388 block_to_read->second.giver.first =
false;
1391 block_to_read->second.read_req = swappable_blocks[block_to_read->first].read_async();
1399 writing_block->second->write_req->wait();
1400 delete writing_block->second;
1401 write_scheduled_blocks.erase(writing_block);
1410 if (it != write_scheduled_blocks.end())
1419 if (schedule_meta->second.giver.first)
1421 wait_on_write(schedule_meta->second.giver.second);
1422 schedule_meta->second.giver.first =
false;
1431 wait_on_write(schedule_meta);
1432 if (schedule_meta->second.read_req.valid())
1434 schedule_meta->second.read_req->wait();
1435 schedule_meta->second.read_req = 0;
1444 wait_on_write(schedule_meta);
1446 schedule_meta->second.reserved_iblock = 0;
1453 for (
typename std::deque<block_scheduler_operation>::reverse_iterator
1454 rit = schedule_meta->second.operations.rbegin() + ignore_first;
1455 rit != schedule_meta->second.operations.rend(); ++rit)
1459 case block_scheduler_type::op_acquire:
1460 case block_scheduler_type::op_acquire_uninitialized:
1463 case block_scheduler_type::op_release:
1464 case block_scheduler_type::op_release_dirty:
1466 case block_scheduler_type::op_deinitialize:
1467 if (swappable_blocks[schedule_meta->first].is_dirty())
1470 case block_scheduler_type::op_initialize:
1471 case block_scheduler_type::op_extract_external_block:
1482 for (
typename std::deque<block_scheduler_operation>::reverse_iterator
1483 rit = schedule_meta->second.operations.rbegin() + 1;
1484 rit != schedule_meta->second.operations.rend(); ++rit)
1488 case block_scheduler_type::op_acquire:
1489 case block_scheduler_type::op_acquire_uninitialized:
1490 case block_scheduler_type::op_release:
1492 case block_scheduler_type::op_release_dirty:
1493 case block_scheduler_type::op_deinitialize:
1494 case block_scheduler_type::op_initialize:
1497 case block_scheduler_type::op_extract_external_block:
1508 return swappable_blocks[schedule_meta->first].is_initialized()
1509 && schedule_meta->second.operations.rbegin() + ignore_first != schedule_meta->second.operations.rend()
1510 && *(schedule_meta->second.operations.rbegin() + ignore_first) == block_scheduler_type::op_acquire;
1515 schedule_meta->second.operations.pop_back();
1516 if (schedule_meta->second.operations.empty())
1518 assert(! schedule_meta->second.giver.first);
1519 scheduled_blocks.erase(schedule_meta);
1525 TLX_LOG1 <<
"block_scheduler_algorithm_offline_lru_prefetching: " << err_msg <<
". Switching to block_scheduler_algorithm_online.";
1530 delete bs.switch_algorithm_to(new_algo);
1535 { return_free_internal_block_to_block_scheduler(iblock); }
1539 while (next_op_to_schedule != prediction_sequence.end())
1542 std::pair<scheduled_blocks_iterator, bool> ins_res = scheduled_blocks.insert(
1544 next_op_to_schedule->id,
1549 if (! ins_res.second)
1550 schedule_meta->second.operations.push_front(next_op_to_schedule->op);
1551 SwappableBlockType& sblock = swappable_blocks[next_op_to_schedule->id];
1554 if (next_op_to_schedule->op == block_scheduler_type::op_acquire ||
1555 next_op_to_schedule->op == block_scheduler_type::op_acquire_uninitialized)
1557 if (sblock.is_internal())
1559 if (free_evictable_blocks.erase(next_op_to_schedule->id))
1560 scheduled_evictable_blocks.insert(next_op_to_schedule->id);
1564 if (! schedule_meta->second.reserved_iblock)
1568 schedule_meta->second.reserved_iblock = get_free_internal_block_from_block_scheduler();
1569 if (! schedule_meta->second.reserved_iblock)
1572 if (free_evictable_blocks.empty())
1577 scheduled_blocks.erase(ins_res.first);
1579 schedule_meta->second.operations.pop_front();
1586 scheduled_blocks.find(giver) == scheduled_blocks.end() ||
1587 !shall_keep_internal_block(scheduled_blocks.find(giver),
false)
1591 schedule_meta->second.giver.first = (wrr !=
nullptr);
1592 schedule_meta->second.giver.second = giver;
1593 schedule_meta->second.reserved_iblock = swappable_blocks[giver].detach_internal_block();
1595 wrr->
taker = schedule_meta;
1598 if (shall_be_read(schedule_meta,
false))
1602 sblock.attach_internal_block(schedule_meta->second.reserved_iblock);
1603 schedule_meta->second.reserved_iblock = 0;
1604 scheduled_evictable_blocks.insert(next_op_to_schedule->id);
1605 schedule_read(schedule_meta);
1610 else if (next_op_to_schedule->op == block_scheduler_type::op_deinitialize)
1612 if (sblock.is_dirty())
1613 if (free_evictable_blocks.erase(next_op_to_schedule->id))
1614 scheduled_evictable_blocks.insert(next_op_to_schedule->id);
1617 ++next_op_to_schedule;
1619 for (
typename std::set<swappable_block_identifier_type>::iterator it = free_evictable_blocks.begin();
1620 it != free_evictable_blocks.end(); ++it)
1622 if (! write_scheduled_blocks.count(*it))
1623 schedule_write(*it);
1632 next_op_to_schedule = prediction_sequence.begin();
1633 if (get_algorithm_from_block_scheduler())
1634 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
1635 free_evictable_blocks.insert(get_algorithm_from_block_scheduler()->evictable_blocks_pop());
1636 schedule_next_operations();
1642 if (! scheduled_blocks.empty())
1643 TLX_LOG1 <<
"deinit while scheduled_blocks not empty";
1645 if (! scheduled_evictable_blocks.empty())
1646 TLX_LOG1 <<
"deinit while scheduled_evictable_blocks not empty";
1649 free_evictable_blocks.insert(scheduled_evictable_blocks.begin(), scheduled_evictable_blocks.end());
1653 scheduled_evictable_blocks.clear();
1654 while (! scheduled_blocks.empty())
1658 if (it->second.reserved_iblock)
1659 return_free_internal_block(it->second.reserved_iblock);
1660 scheduled_blocks.erase(it);
1662 while (! write_scheduled_blocks.empty())
1672 { init(get_algorithm_from_block_scheduler()); }
1682 if (! free_evictable_blocks.empty())
1683 TLX_LOG1 <<
"Destructing block_scheduler_algorithm_offline_lru_prefetching that still holds evictable blocks. They get deinitialized.";
1684 while (! free_evictable_blocks.empty())
1686 SwappableBlockType& sblock = swappable_blocks[
pop_begin(free_evictable_blocks)];
1688 return_free_internal_block(iblock);
1695 return free_evictable_blocks.empty();
1699 {
return pop_begin(free_evictable_blocks); }
1703 assert(! prediction_sequence.empty());
1705 prediction_sequence.front().op ==
1706 ((uninitialized) ? block_scheduler_type::op_acquire_uninitialized : block_scheduler_type::op_acquire)
1708 assert(prediction_sequence.front().id == sbid);
1709 prediction_sequence.pop_front();
1711 assert(schedule_meta != scheduled_blocks.end());
1713 schedule_meta->second.operations.back() ==
1714 ((uninitialized) ? block_scheduler_type::op_acquire_uninitialized : block_scheduler_type::op_acquire)
1717 SwappableBlockType& sblock = swappable_blocks[sbid];
1723 if (sblock.is_internal())
1725 if (! sblock.is_acquired())
1728 size_t t = scheduled_evictable_blocks.erase(sbid);
1732 wait_on_read(schedule_meta);
1738 assert(uninitialized || ! sblock.is_initialized());
1740 sblock.attach_internal_block(get_ready_block(schedule_meta));
1743 if (! uninitialized)
1744 sblock.fill_default();
1747 operation_done(schedule_meta);
1748 return sblock.get_internal_block();
1753 assert(! prediction_sequence.empty());
1755 prediction_sequence.front().op ==
1756 ((
dirty) ? block_scheduler_type::op_release_dirty : block_scheduler_type::op_release)
1758 assert(prediction_sequence.front().id == sbid);
1759 prediction_sequence.pop_front();
1761 assert(schedule_meta != scheduled_blocks.end());
1763 schedule_meta->second.operations.back() ==
1764 ((
dirty) ? block_scheduler_type::op_release_dirty : block_scheduler_type::op_release)
1767 SwappableBlockType& sblock = swappable_blocks[sbid];
1768 sblock.make_dirty_if(dirty);
1770 if (! sblock.is_acquired())
1772 if (sblock.is_dirty() || sblock.is_external())
1775 if (shall_keep_internal_block(schedule_meta))
1778 scheduled_evictable_blocks.insert(sbid);
1779 if (shall_be_cleaned(schedule_meta))
1780 schedule_write(sbid);
1785 free_evictable_blocks.insert(sbid);
1786 if (next_op_to_schedule != prediction_sequence.end())
1787 schedule_next_operations();
1789 if (! write_scheduled_blocks.count(sbid))
1790 schedule_write(sbid);
1797 if (shall_keep_internal_block(schedule_meta))
1799 schedule_meta->second.reserved_iblock = sblock.detach_internal_block();
1803 return_free_internal_block(sblock.detach_internal_block());
1804 if (next_op_to_schedule != prediction_sequence.end())
1805 schedule_next_operations();
1809 operation_done(schedule_meta);
1814 assert(! prediction_sequence.empty());
1815 assert(prediction_sequence.front().op == block_scheduler_type::op_deinitialize);
1816 assert(prediction_sequence.front().id == sbid);
1817 prediction_sequence.pop_front();
1819 assert(schedule_meta != scheduled_blocks.end());
1820 assert(schedule_meta->second.operations.back() == block_scheduler_type::op_deinitialize);
1822 SwappableBlockType& sblock = swappable_blocks[sbid];
1823 if (sblock.is_evictable())
1826 if (shall_keep_internal_block(schedule_meta,
false))
1828 t = scheduled_evictable_blocks.erase(sbid);
1830 TLX_LOG1 <<
"dirty block not scheduled on deinitialize";
1831 t = free_evictable_blocks.erase(sbid);
1835 t = free_evictable_blocks.erase(sbid);
1840 if (shall_keep_internal_block(schedule_meta))
1842 schedule_meta->second.reserved_iblock = iblock;
1846 return_free_internal_block(iblock);
1847 if (next_op_to_schedule != prediction_sequence.end())
1848 schedule_next_operations();
1851 operation_done(schedule_meta);
1856 assert(! prediction_sequence.empty());
1857 assert(prediction_sequence.front().op == block_scheduler_type::op_initialize);
1858 assert(prediction_sequence.front().id == sbid);
1859 prediction_sequence.pop_front();
1861 assert(schedule_meta != scheduled_blocks.end());
1862 assert(schedule_meta->second.operations.back() == block_scheduler_type::op_initialize);
1864 SwappableBlockType& sblock = swappable_blocks[sbid];
1865 sblock.initialize(eblock);
1866 if (shall_be_read(schedule_meta))
1868 sblock.attach_internal_block(schedule_meta->second.reserved_iblock);
1869 schedule_meta->second.reserved_iblock = 0;
1870 scheduled_evictable_blocks.insert(sbid);
1871 schedule_read(schedule_meta);
1873 operation_done(schedule_meta);
1878 assert(! prediction_sequence.empty());
1879 assert(prediction_sequence.front().op == block_scheduler_type::op_extract_external_block);
1880 assert(prediction_sequence.front().id == sbid);
1881 prediction_sequence.pop_front();
1883 assert(schedule_meta != scheduled_blocks.end());
1884 assert(schedule_meta->second.operations.back() == block_scheduler_type::op_extract_external_block);
1886 SwappableBlockType& sblock = swappable_blocks[sbid];
1887 wait_on_write(sbid);
1888 operation_done(schedule_meta);
1889 return sblock.extract_external_block();
1895 #endif // !FOXXLL_MNG_BLOCK_SCHEDULER_HEADER write_scheduled_blocks_type write_scheduled_blocks
Holds swappable_blocks, whose internal block has been taken away but the clean did not finish yet...
block_scheduler_algorithm_offline_lfd(block_scheduler_type &bs)
scheduled_blocks_iterator taker
virtual void deinitialize(swappable_block_identifier_type sbid)
priority(const SwappableBlockType &sblock, const std::pair< bool, time_type > &t)
internal_block_type & get_internal_block()
Get a reference to the data-block. Has to be acquired.
internal_block_type * get_free_internal_block()
virtual void initialize(swappable_block_identifier_type sbid, external_block_type)
void free_external_block()
void return_free_internal_block(internal_block_type *iblock)
virtual swappable_block_identifier_type evictable_blocks_pop()
static uint_pair max()
return an uint_pair instance containing the largest value possible
internal_block_type * internal_data
external_data.valid if no associated space on disk
virtual ~block_scheduler_algorithm_offline_lru_prefetching()
typename SwappableBlockType::internal_block_type internal_block_type
void init(block_scheduler_algorithm_type *old_algo)
static size_t disk_allocation_offset
bool is_simulating() const
addressable_fifo_queue< swappable_block_identifier_type > evictable_blocks
Holds swappable blocks, whose internal block can be freed, i.e. that are internal but unacquired...
virtual void explicit_timestep()
void wait_on_read(const scheduled_blocks_iterator &schedule_meta)
tlx::counting_ptr< request > request_ptr
A reference counting pointer for request.
scheduled_blocks_type scheduled_blocks
Holds not internal swappable_blocks, whose next access has already been scheduled.
void wait_on_write(const write_scheduled_blocks_iterator &writing_block)
internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
std::map< swappable_block_identifier_type, scheduled_block_meta > scheduled_blocks_type
internal_block_type & get_internal_block(const swappable_block_identifier_type sbid) const
bool is_external() const
If it has an external_block that holds valid data.
bool is_evictable() const
If it holds an internal_block but does not need it.
virtual void swappable_blocks_resize(swappable_block_identifier_type)
typename block_scheduler_type::internal_block_type internal_block_type
void release()
Release the block, i.e. subduct a reference. Has to be acquired.
static constexpr bool debug
void attach_internal_block(internal_block_type *iblock)
Attach an internal_block, making the block internal. Has to be not internal.
block_scheduler_algorithm_online_lru(block_scheduler_type &bs)
std::set< swappable_block_identifier_type > scheduled_evictable_blocks
external_block_type external_data
prediction_sequence_element(block_scheduler_operation op, swappable_block_identifier_type id, time_type time)
prediction_sequence_type prediction_sequence
Block scheduling algorithm caching via the longest forward distance policy (offline).
std::stack< internal_block_type * > free_internal_blocks
holds free internal_blocks with attributes reset.
virtual bool is_simulating() const
bool erase(const KeyType &e)
virtual ~block_scheduler_algorithm_offline_lfd()
typename block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
virtual ~block_scheduler_algorithm_online_lru()
internal_block_type & acquire()
void fill_default()
Fill block with default data, is supposed to be overwritten by subclass. Has to be internal...
void operation_done(scheduled_blocks_iterator &schedule_meta)
void read_sync()
Read synchronously from external_block to internal_block. Has to be internal and have an external_blo...
block_scheduler_type & bs
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)=0
virtual void explicit_timestep()
bool valid() const noexcept
test for a non-nullptr pointer
void initialize(const swappable_block_identifier_type sbid, external_block_type eblock)
typename write_scheduled_blocks_type::iterator write_scheduled_blocks_iterator
block_scheduler_algorithm_offline_lfd(block_scheduler_algorithm_type *old)
block_scheduler_algorithm< SwappableBlockType > * switch_algorithm_to(block_scheduler_algorithm< SwappableBlockType > *new_algo)
Pseudo block scheduling algorithm only recording the request sequence.
void delete_block(const BID< BlockSize > &bid)
void return_free_internal_block(internal_block_type *iblock)
read_after_write(write_read_request *write_read_req)
void return_free_internal_block_to_block_scheduler(internal_block_type *iblock)
Return an internal_block to the block_scheduler.
block_scheduler_algorithm_online_lru(block_scheduler_algorithm_type *old)
Container::value_type pop_begin(Container &c)
internal_block_type * get_free_internal_block()
std::vector< size_t > reference_counts
typename write_scheduled_blocks_type::reference write_scheduled_blocks_reference
std::pair< handle, bool > insert(const KeyType &e, const PriorityType o)
virtual swappable_block_identifier_type evictable_blocks_pop()
block_scheduler(const size_t max_internal_memory)
request_ptr read_async(completion_handler on_cmpl=completion_handler())
block_scheduler_algorithm< SwappableBlockType > * get_current_algorithm() const
Return the current algorithm.
virtual void deinitialize(swappable_block_identifier_type sbid)
typename block_scheduler_type::block_scheduler_operation block_scheduler_operation
internal_block_type dummy_block
void schedule_next_operations()
void get_external_block()
std::stack< swappable_block_identifier_type > evictable_blocks
Holds swappable blocks, whose internal block can be freed, i.e. that are internal but unacquired...
internal_block_type * get_free_internal_block()
bool shall_keep_internal_block(const scheduled_blocks_iterator &schedule_meta, const bool ignore_first=true) const
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
external_block_type extract_external_block()
virtual void deinitialize(swappable_block_identifier_type sbid)=0
typename block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
size_t remaining_internal_blocks
prediction_sequence_type::iterator next_op_to_schedule
virtual void deinitialize(swappable_block_identifier_type sbid)
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
bool is_initialized(const swappable_block_identifier_type sbid) const
virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock)
virtual bool is_initialized(const swappable_block_identifier_type sbid) const
void return_free_internal_block(internal_block_type *iblock)
Return an internal_block to the freelist.
const internal_block_type & get_internal_block() const
Get a reference to the data-block. Has to be acquired.
tlx::delegate< void(request *r, bool success)> completion_handler
completion handler
typename internal_block_type::bid_type external_block_type
typename block_scheduler_type::external_block_type external_block_type
void clean_sync()
Write synchronously from internal_block to external_block if necessary.
typename scheduled_blocks_type::reference scheduled_blocks_reference
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)
virtual void release(swappable_block_identifier_type sbid, const bool dirty)=0
swappable_block_identifier_type allocate_swappable_block()
std::stack< internal_block_type * > internal_blocks_blocks
Stores pointers to arrays of internal_blocks. Used to deallocate them only.
void initialize(external_block_type eblock)
block_scheduler_algorithm_simulation(block_scheduler_algorithm_type *old)
virtual ~block_scheduler_algorithm_simulation()
void swap(CountingPtr< A, D > &a1, CountingPtr< A, D > &a2) noexcept
std::remove_const< Integral >::type div_ceil(Integral n, Integral2 d)
virtual bool is_simulating() const
block_scheduler_algorithm * get_algorithm_from_block_scheduler()
swappable_block()
Create in uninitialized state.
static const size_t raw_block_size
external_block_type extract_external_block(const swappable_block_identifier_type sbid)
bool is_acquired() const
If it is acquired.
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)
void release(const swappable_block_identifier_type sbid, const bool dirty)
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
virtual swappable_block_identifier_type evictable_blocks_pop()
typename block_scheduler_algorithm_type::time_type time_type
virtual bool evictable_blocks_empty()=0
std::list< prediction_sequence_element > prediction_sequence_type
typename block_scheduler_type::prediction_sequence_type prediction_sequence_type
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
write_read_request * schedule_write(const swappable_block_identifier_type sbid)
virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock)=0
static instance_pointer get_instance()
return instance or create base instance if empty
virtual bool evictable_blocks_empty()
internal_block_type * get_free_internal_block_from_block_scheduler()
block_scheduler_algorithm_type * give_up(std::string err_msg="detected some error in the prediction sequence")
void init(block_scheduler_algorithm_type *old_algo)
block_scheduler_algorithm(block_scheduler_type &bs)
High-performance smart pointer used as a wrapping reference counting pointer.
typename SwappableBlockType::external_block_type external_block_type
void return_free_internal_block(internal_block_type *iblock)
virtual swappable_block_identifier_type evictable_blocks_pop()
request_ptr clean_async(completion_handler on_cmpl=completion_handler())
block_scheduler_operation
addressable_priority_queue< swappable_block_identifier_type, priority > evictable_blocks
Holds swappable blocks, whose internal block can be freed, i.e. that are internal but unacquired...
std::vector< SwappableBlockType > & swappable_blocks
virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock)
void deinitialize(const swappable_block_identifier_type sbid)
Drop all data in the given block, freeing in- and external memory.
Block scheduling algorithm caching via the least recently used policy (online).
virtual ~block_scheduler_algorithm()
block_scheduler_algorithm< SwappableBlockType > * algo
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
bool shall_be_cleaned(const scheduled_blocks_iterator &schedule_meta) const
static uint_pair min()
return an uint_pair instance containing the smallest value possible
typename std::vector< SwappableBlockType >::size_type swappable_block_identifier_type
virtual swappable_block_identifier_type evictable_blocks_pop()=0
bool is_dirty() const
If the external_block does not hold valid data.
void wait_on_write(const scheduled_blocks_iterator &schedule_meta)
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
std::map< swappable_block_identifier_type, write_read_request * > write_scheduled_blocks_type
internal_block_type * deinitialize()
void free_swappable_block(const swappable_block_identifier_type sbid)
bool erase(const KeyType &e)
const prediction_sequence_type & get_prediction_sequence() const
virtual bool evictable_blocks_empty()
std::priority_queue< swappable_block_identifier_type, std::vector< swappable_block_identifier_type >, std::greater< swappable_block_identifier_type > > free_swappable_blocks
holds indices of free swappable_blocks with attributes reset.
block_scheduler_algorithm(block_scheduler_algorithm *old)
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)=0
std::pair< handle, bool > insert(const KeyType &e)
typename std::vector< SwappableBlockType >::iterator swappable_blocks_iterator
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
void new_block(const DiskAssignFunctor &functor, BID< BlockSize > &bid, size_t alloc_offset=0)
Allocates a new block according to the strategy given by functor and stores the block identifier to b...
void return_free_internal_block(internal_block_type *iblock)
typename block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
request_ptr write(const bid_type &bid, completion_handler on_complete=completion_handler())
Writes block to the disk(s).
typename block_scheduler_type::time_type time_type
virtual bool evictable_blocks_empty()
Request object encapsulating basic properties like file and offset.
internal_block_type * get_ready_block(const scheduled_blocks_iterator &schedule_meta)
swappable_block_identifier_type id
typename block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
bool is_initialized() const
If it has some valid data (in- or external).
block_scheduler_algorithm_offline_lru_prefetching(block_scheduler_type &bs)
bool make_dirty_if(const bool make_dirty)
std::set< swappable_block_identifier_type > free_evictable_blocks
Holds swappable blocks, whose internal block can be freed, i.e. that are internal but unacquired...
typename block_scheduler_type::prediction_sequence_element prediction_sequence_element_type
virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock)
void wait_on_write(const swappable_block_identifier_type &writing_block)
typename scheduled_blocks_type::iterator scheduled_blocks_iterator
bool shall_be_read(const scheduled_blocks_iterator &schedule_meta, const bool ignore_first=true) const
std::deque< std::pair< bool, time_type > > next_use
Stores for the sequence of releases extracted from the prediction_sequence: (true, timestamp of the blocks next acquire) if it is acquired next (false, 0) if it is deinitialized next (false, 1) if it is not accessed any more (false, 2) if it is extracted next (false, 3) if it is initialized next.
bool operator<(const uint_pair &b) const
less-than comparison operator
bool has_external_block() const
If it has an external_block.
virtual void swappable_blocks_resize(swappable_block_identifier_type size)
virtual const prediction_sequence_type & get_prediction_sequence() const
request_ptr read(const bid_type &bid, completion_handler on_complete=completion_handler())
Reads block from the disk(s).
block_scheduler_operation op
block_scheduler_algorithm_simulation(block_scheduler_type &bs)
typename block_scheduler_type::internal_block_type internal_block_type
static const size_t max_internal_blocks_alloc_at_once
typename block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
bool try_interrupt_read(const write_scheduled_blocks_iterator &writing_block)
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
virtual bool is_initialized(const swappable_block_identifier_type sbid) const
swappable_blocks_iterator block_to_start_read
Interface of a block scheduling algorithm.
internal_block_type * detach_internal_block()
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)
const size_t max_internal_blocks
void schedule_read(scheduled_blocks_iterator block_to_read)
std::vector< SwappableBlockType > swappable_blocks
temporary blocks that will not be needed after algorithm termination.
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
bool is_internal() const
If it has an internal_block. The internal_block implicitly holds valid data.
virtual bool evictable_blocks_empty()
#define TLX_LOG
Default logging method: output if the local debug variable is true.
block_scheduler_algorithm_offline_lru_prefetching(block_scheduler_algorithm_type *old)
virtual void deinitialize(swappable_block_identifier_type sbid)
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)