13 #ifndef STXXL_MNG_BLOCK_SCHEDULER_HEADER
14 #define STXXL_MNG_BLOCK_SCHEDULER_HEADER
35 template <
typename ValueType,
unsigned BlockSize>
39 static const unsigned_type raw_block_size = BlockSize *
sizeof(ValueType);
54 { block_manager::get_instance()->new_block(
striping(), external_data, ++disk_allocation_offset); }
58 block_manager::get_instance()->delete_block(external_data);
65 : external_data() , internal_data(0), dirty(false), reference_count(0) { }
71 {
return (internal_data != NULL); }
79 {
return external_data.valid(); }
83 {
return has_external_block() && ! is_dirty(); }
87 {
return reference_count > 0; }
91 {
return ! is_acquired() && is_internal(); }
95 {
return is_internal() || is_external(); }
101 assert(is_acquired());
102 return dirty = make_dirty || dirty;
109 assert(is_internal());
111 return *internal_data;
117 assert(is_acquired());
124 assert(is_acquired());
125 return *internal_data;
131 assert(is_acquired());
132 return *internal_data;
142 assert(is_internal());
143 assert(has_external_block());
148 return internal_data->read(external_data, on_cmpl);
153 { read_async()->wait(); }
161 if (! has_external_block())
162 get_external_block();
167 return internal_data->write(external_data, on_cmpl);
181 assert(! is_internal());
182 internal_data = iblock;
189 assert(is_evictable());
201 assert(! is_acquired());
204 if (has_external_block())
205 free_external_block();
216 assert(! is_initialized());
217 external_data = eblock;
224 assert(! is_internal());
231 template <
typename ValueType,
unsigned BlockSize>
232 unsigned_type swappable_block<ValueType, BlockSize>::disk_allocation_offset = 0;
234 template <
class SwappableBlockType>
237 template <
class SwappableBlockType>
249 template <
class SwappableBlockType>
283 op_extract_external_block
294 : op(op), id(id), time(time) { }
313 std::priority_queue<swappable_block_identifier_type, std::vector<swappable_block_identifier_type>,
322 if (! free_internal_blocks.empty())
326 free_internal_blocks.pop();
329 else if (remaining_internal_blocks > 0)
332 int_type num_blocks =
std::min(max_internal_blocks_alloc_at_once, remaining_internal_blocks);
333 remaining_internal_blocks -= num_blocks;
335 internal_blocks_blocks.push(iblocks);
336 for (
int_type i = num_blocks - 1; i > 0; --i)
337 free_internal_blocks.push(iblocks + i);
349 { free_internal_blocks.push(iblock); }
356 remaining_internal_blocks(max_internal_blocks),
366 int_type num_freed_internal_blocks = 0;
367 if (free_swappable_blocks.size() != swappable_blocks.size())
370 STXXL_ERRMSG(
"not all swappable_blocks are free, those not acquired will be deinitialized");
372 for (
typename std::vector<SwappableBlockType>::iterator it = swappable_blocks.begin();
373 it != swappable_blocks.end(); ++it)
375 if (! it->is_acquired() && it->deinitialize())
377 num_freed_internal_blocks++;
380 if (
int_type nlost = (max_internal_blocks - remaining_internal_blocks)
381 - (free_internal_blocks.size() + num_freed_internal_blocks)) {
382 STXXL_ERRMSG(nlost <<
" internal_blocks are lost. They will get deallocated.");
384 while (! internal_blocks_blocks.empty())
386 delete[] internal_blocks_blocks.top();
387 internal_blocks_blocks.pop();
396 {
return algo->acquire(sbid, uninitialized); }
403 { algo->release(sbid, dirty); }
407 { algo->deinitialize(sbid); }
416 { algo->initialize(sbid, eblock); }
423 {
return algo->extract_external_block(sbid); }
429 {
return algo->is_initialized(sbid); }
434 { algo->explicit_timestep(); }
439 {
return swappable_blocks[sbid].get_internal_block(); }
446 if (free_swappable_blocks.empty())
449 sbid = swappable_blocks.size();
450 swappable_blocks.resize(sbid + 1);
451 algo->swappable_blocks_resize(sbid + 1);
456 sbid = free_swappable_blocks.top();
457 free_swappable_blocks.pop();
467 free_swappable_blocks.push(sbid);
473 {
return algo->is_simulating(); }
480 assert(&new_algo->
bs ==
this);
495 {
return algo->get_prediction_sequence(); }
499 std::vector<request_ptr> requests;
500 while (! algo->evictable_blocks_empty())
503 request_ptr rq = swappable_blocks[sbid].clean_async();
505 requests.push_back(rq);
506 return_free_internal_block(swappable_blocks[sbid].detach_internal_block());
508 for (
typename std::vector<request_ptr>::reverse_iterator it = requests.rbegin();
509 it != requests.rend(); ++it)
516 template <
class SwappableBlockType>
517 const int_type block_scheduler<SwappableBlockType>::max_internal_blocks_alloc_at_once = 128;
520 template <
class SwappableBlockType>
521 class block_scheduler_algorithm :
private noncopyable
544 {
return bs.get_free_internal_block(); }
548 { bs.return_free_internal_block(iblock); }
553 swappable_blocks(bs.swappable_blocks)
558 swappable_blocks(bs.swappable_blocks)
563 virtual bool evictable_blocks_empty() = 0;
564 virtual swappable_block_identifier_type evictable_blocks_pop() = 0;
567 virtual internal_block_type & acquire(
const swappable_block_identifier_type sbid,
const bool uninitialized =
false) = 0;
568 virtual void release(swappable_block_identifier_type sbid,
const bool dirty) = 0;
569 virtual void deinitialize(swappable_block_identifier_type sbid) = 0;
570 virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock) = 0;
571 virtual external_block_type extract_external_block(swappable_block_identifier_type sbid) = 0;
574 {
return swappable_blocks[sbid].is_initialized(); }
580 {
return prediction_sequence; }
584 template <
class SwappableBlockType>
585 class block_scheduler_algorithm_online_lru :
public block_scheduler_algorithm<SwappableBlockType>
594 using block_scheduler_algorithm_type::bs;
595 using block_scheduler_algorithm_type::swappable_blocks;
596 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
597 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
598 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
609 assert(! evictable_blocks.empty());
610 return swappable_blocks[evictable_blocks.pop()].detach_internal_block();
614 { return_free_internal_block_to_block_scheduler(iblock); }
618 if (get_algorithm_from_block_scheduler())
619 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
620 evictable_blocks.insert(get_algorithm_from_block_scheduler()->evictable_blocks_pop());
634 if (! evictable_blocks.empty())
635 STXXL_ERRMSG(
"Destructing block_scheduler_algorithm_online that still holds evictable blocks. They get deinitialized.");
636 while (! evictable_blocks.empty())
638 SwappableBlockType& sblock = swappable_blocks[evictable_blocks.pop()];
640 return_free_internal_block(iblock);
645 {
return evictable_blocks.empty(); }
648 {
return evictable_blocks.pop(); }
652 SwappableBlockType& sblock = swappable_blocks[sbid];
658 if (sblock.is_internal())
660 if (! sblock.is_acquired())
662 evictable_blocks.erase(sbid);
665 else if (sblock.is_initialized())
669 sblock.attach_internal_block(get_free_internal_block());
679 sblock.attach_internal_block(get_free_internal_block());
683 sblock.fill_default();
685 return sblock.get_internal_block();
690 SwappableBlockType& sblock = swappable_blocks[sbid];
691 sblock.make_dirty_if(dirty);
693 if (! sblock.is_acquired())
695 if (sblock.is_dirty() || sblock.is_external())
697 evictable_blocks.insert(sbid);
700 return_free_internal_block(sblock.detach_internal_block());
706 SwappableBlockType& sblock = swappable_blocks[sbid];
707 if (sblock.is_evictable())
708 evictable_blocks.erase(sbid);
710 return_free_internal_block(iblock);
715 SwappableBlockType& sblock = swappable_blocks[sbid];
716 sblock.initialize(eblock);
721 SwappableBlockType& sblock = swappable_blocks[sbid];
722 if (sblock.is_evictable())
723 evictable_blocks.erase(sbid);
724 if (sblock.is_internal())
725 return_free_internal_block(sblock.detach_internal_block());
726 return sblock.extract_external_block();
731 template <
class SwappableBlockType>
743 using block_scheduler_algorithm_type::bs;
744 using block_scheduler_algorithm_type::prediction_sequence;
745 using block_scheduler_algorithm_type::swappable_blocks;
746 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
747 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
748 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
758 { return_free_internal_block_to_block_scheduler(iblock); }
762 if (get_algorithm_from_block_scheduler())
763 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
764 evictable_blocks.push(get_algorithm_from_block_scheduler()->evictable_blocks_pop());
766 reference_counts[i] = swappable_blocks[i].is_initialized();
773 last_op_release(false),
774 reference_counts(swappable_blocks.size())
780 last_op_release(false),
781 reference_counts(swappable_blocks.size())
786 if (! evictable_blocks.empty())
787 STXXL_ERRMSG(
"Destructing block_scheduler_algorithm_record_prediction_sequence that still holds evictable blocks. They get deinitialized.");
788 while (! evictable_blocks.empty())
790 SwappableBlockType& sblock = swappable_blocks[evictable_blocks.top()];
792 return_free_internal_block(iblock);
793 evictable_blocks.pop();
798 {
return evictable_blocks.empty(); }
803 evictable_blocks.pop();
809 ++reference_counts[sbid];
810 last_op_release =
false;
812 prediction_sequence.push_back(
816 prediction_sequence.push_back(
824 --reference_counts[sbid] += dirty;
825 time_count += ! last_op_release;
826 last_op_release =
true;
828 prediction_sequence.push_back(
832 prediction_sequence.push_back(
839 reference_counts[sbid] =
false;
840 prediction_sequence.push_back(
847 reference_counts[sbid] =
true;
848 prediction_sequence.push_back(
855 reference_counts[sbid] =
false;
856 prediction_sequence.push_back(
864 reference_counts.resize(size, 0);
869 return reference_counts[sbid] > 0;
880 template <
class SwappableBlockType>
892 using block_scheduler_algorithm_type::bs;
893 using block_scheduler_algorithm_type::swappable_blocks;
894 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
895 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
896 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
903 priority(
const SwappableBlockType& sblock,
const std::pair<bool, time_type>& t)
926 {
return p > right.
p; }
947 assert(! evictable_blocks.empty());
948 return swappable_blocks[evictable_blocks.pop()].detach_internal_block();
952 { return_free_internal_block_to_block_scheduler(iblock); }
956 std::vector<std::pair<bool, time_type> >
957 blocks_next_acquire(swappable_blocks.size(), std::make_pair(
false, 1));
962 for (
typename prediction_sequence_type::const_reverse_iterator it = ps.rbegin(); it != ps.rend(); ++it)
966 case (block_scheduler_type::op_acquire):
967 case (block_scheduler_type::op_acquire_uninitialized):
968 blocks_next_acquire[it->id] = std::make_pair(
true, it->time);
970 case (block_scheduler_type::op_release):
971 case (block_scheduler_type::op_release_dirty):
972 next_use.push_front(blocks_next_acquire[it->id]);
974 case (block_scheduler_type::op_deinitialize):
975 blocks_next_acquire[it->id] = std::make_pair(
false, 0);
977 case (block_scheduler_type::op_initialize):
978 blocks_next_acquire[it->id] = std::make_pair(
false, 3);
980 case (block_scheduler_type::op_extract_external_block):
981 blocks_next_acquire[it->id] = std::make_pair(
false, 2);
986 if (get_algorithm_from_block_scheduler())
988 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
992 evictable_blocks.insert(sbid,
priority(swappable_blocks[sbid], blocks_next_acquire[sbid]));
1000 { init(get_algorithm_from_block_scheduler()); }
1009 if (! evictable_blocks.empty())
1010 STXXL_ERRMSG(
"Destructing block_scheduler_algorithm_offline_lfd that still holds evictable blocks. They get deinitialized.");
1011 while (! evictable_blocks.empty())
1013 SwappableBlockType& sblock = swappable_blocks[evictable_blocks.pop()];
1015 return_free_internal_block(iblock);
1020 {
return evictable_blocks.empty(); }
1023 {
return evictable_blocks.pop(); }
1027 SwappableBlockType& sblock = swappable_blocks[sbid];
1033 if (sblock.is_internal())
1035 if (! sblock.is_acquired())
1037 evictable_blocks.erase(sbid);
1040 else if (sblock.is_initialized())
1044 sblock.attach_internal_block(get_free_internal_block());
1045 if (! uninitialized)
1054 sblock.attach_internal_block(get_free_internal_block());
1057 if (! uninitialized)
1058 sblock.fill_default();
1060 return sblock.get_internal_block();
1065 if (next_use.empty())
1067 STXXL_ERRMSG(
"block_scheduler_algorithm_offline_lfd got release-request but prediction sequence ended. Switching to block_scheduler_algorithm_online.");
1071 old_algo = bs.switch_algorithm_to(new_algo);
1073 new_algo->
release(sbid, dirty);
1078 SwappableBlockType& sblock = swappable_blocks[sbid];
1079 sblock.make_dirty_if(dirty);
1081 if (! sblock.is_acquired())
1083 if (sblock.is_dirty() || sblock.is_external())
1085 evictable_blocks.insert(sbid,
priority(swappable_blocks[sbid], next_use.front()));
1088 return_free_internal_block(sblock.detach_internal_block());
1090 next_use.pop_front();
1095 SwappableBlockType& sblock = swappable_blocks[sbid];
1096 if (sblock.is_evictable())
1097 evictable_blocks.erase(sbid);
1099 return_free_internal_block(iblock);
1104 SwappableBlockType& sblock = swappable_blocks[sbid];
1105 sblock.initialize(eblock);
1110 SwappableBlockType& sblock = swappable_blocks[sbid];
1111 if (sblock.is_evictable())
1112 evictable_blocks.erase(sbid);
1113 if (sblock.is_internal())
1114 return_free_internal_block(sblock.detach_internal_block());
1115 return sblock.extract_external_block();
1121 template <
class SwappableBlockType>
1145 using block_scheduler_algorithm_type::bs;
1146 using block_scheduler_algorithm_type::swappable_blocks;
1147 using block_scheduler_algorithm_type::get_algorithm_from_block_scheduler;
1148 using block_scheduler_algorithm_type::get_free_internal_block_from_block_scheduler;
1149 using block_scheduler_algorithm_type::return_free_internal_block_to_block_scheduler;
1150 using block_scheduler_algorithm_type::prediction_sequence;
1161 : write_done_soon(false), shall_read(false), block_to_start_read(), taker(), write_req(0) { }
1169 : wrr(write_read_req) { }
1173 wrr->write_done_soon =
true;
1174 if (wrr->shall_read)
1175 wrr->taker->second.read_req = wrr->block_to_start_read->read_async();
1182 std::pair<bool, swappable_block_identifier_type>
giver;
1187 : reserved_iblock(0),
1191 { operations.push_front(op); }
1212 SwappableBlockType& sblock = swappable_blocks[sbid];
1217 bool t = write_scheduled_blocks.insert(std::make_pair(sbid, wrr)).second;
1235 writing_block->second->shall_read =
false;
1237 if (! writing_block->second->write_done_soon)
1242 wait_on_write(writing_block);
1244 if (taker.second.read_req.valid())
1261 if (it != write_scheduled_blocks.end())
1265 if (it->second->shall_read)
1267 if (try_interrupt_read(it))
1270 std::swap(other_block_to_read->second.giver, block_to_read->second.giver);
1271 if (other_block_to_read->second.giver.first)
1274 if (it != write_scheduled_blocks.end())
1275 it->second->taker = other_block_to_read;
1277 other_block_to_read->second.giver.first =
false;
1279 if (block_to_read->second.giver.first)
1282 if (it != write_scheduled_blocks.end())
1283 it->second->taker = block_to_read;
1285 block_to_read->second.giver.first =
false;
1288 internal_block_type* tmp_iblock = swappable_blocks[block_to_read->first].detach_internal_block();
1289 swappable_blocks[block_to_read->first].attach_internal_block(
1290 swappable_blocks[other_block_to_read->first].detach_internal_block());
1291 swappable_blocks[other_block_to_read->first].attach_internal_block(tmp_iblock);
1294 schedule_read(other_block_to_read);
1302 std::swap(other_block_to_read->second.giver, block_to_read->second.giver);
1303 if (other_block_to_read->second.giver.first)
1306 if (it != write_scheduled_blocks.end())
1307 it->second->taker = other_block_to_read;
1309 other_block_to_read->second.giver.first =
false;
1311 if (block_to_read->second.giver.first)
1314 if (it != write_scheduled_blocks.end())
1315 it->second->taker = block_to_read;
1317 block_to_read->second.giver.first =
false;
1320 internal_block_type* tmp_iblock = swappable_blocks[block_to_read->first].detach_internal_block();
1321 swappable_blocks[block_to_read->first].attach_internal_block(
1322 other_block_to_read->second.reserved_iblock);
1323 other_block_to_read->second.reserved_iblock = tmp_iblock;
1330 if (block_to_read->second.giver.first)
1333 if (writing_block != write_scheduled_blocks.end())
1337 writing_block->second->block_to_start_read = swappable_blocks.begin() + block_to_read->first;
1338 writing_block->second->taker = block_to_read;
1339 writing_block->second->shall_read =
true;
1341 if (writing_block->second->write_done_soon)
1345 wait_on_write(writing_block);
1346 block_to_read->second.giver.first =
false;
1347 if (block_to_read->second.read_req.valid())
1356 block_to_read->second.giver.first =
false;
1359 block_to_read->second.read_req = swappable_blocks[block_to_read->first].read_async();
1367 writing_block->second->write_req->wait();
1368 delete writing_block->second;
1369 write_scheduled_blocks.erase(writing_block);
1378 if (it != write_scheduled_blocks.end())
1387 if (schedule_meta->second.giver.first)
1389 wait_on_write(schedule_meta->second.giver.second);
1390 schedule_meta->second.giver.first =
false;
1399 wait_on_write(schedule_meta);
1400 if (schedule_meta->second.read_req.valid())
1402 schedule_meta->second.read_req->wait();
1403 schedule_meta->second.read_req = 0;
1412 wait_on_write(schedule_meta);
1414 schedule_meta->second.reserved_iblock = 0;
1421 for (
typename std::deque<block_scheduler_operation>::reverse_iterator
1422 rit = schedule_meta->second.operations.rbegin() + ignore_first;
1423 rit != schedule_meta->second.operations.rend(); ++rit)
1427 case block_scheduler_type::op_acquire:
1428 case block_scheduler_type::op_acquire_uninitialized:
1431 case block_scheduler_type::op_release:
1432 case block_scheduler_type::op_release_dirty:
1434 case block_scheduler_type::op_deinitialize:
1435 if (swappable_blocks[schedule_meta->first].is_dirty())
return true;
break;
1436 case block_scheduler_type::op_initialize:
1437 case block_scheduler_type::op_extract_external_block:
1448 for (
typename std::deque<block_scheduler_operation>::reverse_iterator
1449 rit = schedule_meta->second.operations.rbegin() + 1;
1450 rit != schedule_meta->second.operations.rend(); ++rit)
1454 case block_scheduler_type::op_acquire:
1455 case block_scheduler_type::op_acquire_uninitialized:
1456 case block_scheduler_type::op_release:
1458 case block_scheduler_type::op_release_dirty:
1459 case block_scheduler_type::op_deinitialize:
1460 case block_scheduler_type::op_initialize:
1463 case block_scheduler_type::op_extract_external_block:
1474 return swappable_blocks[schedule_meta->first].is_initialized()
1475 && schedule_meta->second.operations.rbegin() + ignore_first != schedule_meta->second.operations.rend()
1476 && *(schedule_meta->second.operations.rbegin() + ignore_first) == block_scheduler_type::op_acquire;
1481 schedule_meta->second.operations.pop_back();
1482 if (schedule_meta->second.operations.empty())
1484 assert(! schedule_meta->second.giver.first);
1485 scheduled_blocks.erase(schedule_meta);
1491 STXXL_ERRMSG(
"block_scheduler_algorithm_offline_lru_prefetching: " << err_msg <<
". Switching to block_scheduler_algorithm_online.");
1496 delete bs.switch_algorithm_to(new_algo);
1501 { return_free_internal_block_to_block_scheduler(iblock); }
1505 while (next_op_to_schedule != prediction_sequence.end())
1508 std::pair<scheduled_blocks_iterator, bool> ins_res = scheduled_blocks.insert(
1509 std::make_pair(next_op_to_schedule->id, next_op_to_schedule->op));
1511 if (! ins_res.second)
1512 schedule_meta->second.operations.push_front(next_op_to_schedule->op);
1513 SwappableBlockType& sblock = swappable_blocks[next_op_to_schedule->id];
1516 if (next_op_to_schedule->op == block_scheduler_type::op_acquire
1517 || next_op_to_schedule->op == block_scheduler_type::op_acquire_uninitialized)
1519 if (sblock.is_internal())
1521 if (free_evictable_blocks.erase(next_op_to_schedule->id))
1522 scheduled_evictable_blocks.insert(next_op_to_schedule->id);
1526 if (! schedule_meta->second.reserved_iblock)
1530 schedule_meta->second.reserved_iblock = get_free_internal_block_from_block_scheduler();
1531 if (! schedule_meta->second.reserved_iblock)
1534 if (free_evictable_blocks.empty())
1539 scheduled_blocks.erase(ins_res.first);
1541 schedule_meta->second.operations.pop_front();
1547 assert(scheduled_blocks.find(giver) == scheduled_blocks.end() ||
1548 !shall_keep_internal_block(scheduled_blocks.find(giver),
false));
1551 schedule_meta->second.giver.first = (wrr != NULL);
1552 schedule_meta->second.giver.second = giver;
1553 schedule_meta->second.reserved_iblock = swappable_blocks[giver].detach_internal_block();
1555 wrr->
taker = schedule_meta;
1558 if (shall_be_read(schedule_meta,
false))
1562 sblock.attach_internal_block(schedule_meta->second.reserved_iblock);
1563 schedule_meta->second.reserved_iblock = 0;
1564 scheduled_evictable_blocks.insert(next_op_to_schedule->id);
1565 schedule_read(schedule_meta);
1570 else if (next_op_to_schedule->op == block_scheduler_type::op_deinitialize)
1572 if (sblock.is_dirty())
1573 if (free_evictable_blocks.erase(next_op_to_schedule->id))
1574 scheduled_evictable_blocks.insert(next_op_to_schedule->id);
1577 ++next_op_to_schedule;
1579 for (
typename std::set<swappable_block_identifier_type>::iterator it = free_evictable_blocks.begin();
1580 it != free_evictable_blocks.end(); ++it)
1582 if (! write_scheduled_blocks.count(*it))
1583 schedule_write(*it);
1592 next_op_to_schedule = prediction_sequence.begin();
1593 if (get_algorithm_from_block_scheduler())
1594 while (! get_algorithm_from_block_scheduler()->evictable_blocks_empty())
1595 free_evictable_blocks.insert(get_algorithm_from_block_scheduler()->evictable_blocks_pop());
1596 schedule_next_operations();
1602 if (! scheduled_blocks.empty())
1603 STXXL_MSG(
"deinit while scheduled_blocks not empty");
1604 if (! scheduled_evictable_blocks.empty())
1605 STXXL_MSG(
"deinit while scheduled_evictable_blocks not empty");
1608 free_evictable_blocks.insert(scheduled_evictable_blocks.begin(), scheduled_evictable_blocks.end());
1612 scheduled_evictable_blocks.clear();
1613 while (! scheduled_blocks.empty())
1617 if (it->second.reserved_iblock)
1618 return_free_internal_block(it->second.reserved_iblock);
1619 scheduled_blocks.erase(it);
1621 while (! write_scheduled_blocks.empty())
1631 { init(get_algorithm_from_block_scheduler()); }
1641 if (! free_evictable_blocks.empty())
1642 STXXL_ERRMSG(
"Destructing block_scheduler_algorithm_offline_lru_prefetching that still holds evictable blocks. They get deinitialized.");
1643 while (! free_evictable_blocks.empty())
1645 SwappableBlockType& sblock = swappable_blocks[
pop_begin(free_evictable_blocks)];
1647 return_free_internal_block(iblock);
1654 return free_evictable_blocks.empty();
1658 {
return pop_begin(free_evictable_blocks); }
1662 assert(! prediction_sequence.empty());
1663 assert(prediction_sequence.front().op ==
1664 ((uninitialized) ? block_scheduler_type::op_acquire_uninitialized : block_scheduler_type::op_acquire));
1665 assert(prediction_sequence.front().id == sbid);
1666 prediction_sequence.pop_front();
1668 assert(schedule_meta != scheduled_blocks.end());
1669 assert(schedule_meta->second.operations.back() ==
1670 ((uninitialized) ? block_scheduler_type::op_acquire_uninitialized : block_scheduler_type::op_acquire));
1672 SwappableBlockType& sblock = swappable_blocks[sbid];
1678 if (sblock.is_internal())
1680 if (! sblock.is_acquired())
1683 size_t t = scheduled_evictable_blocks.erase(sbid);
1685 wait_on_read(schedule_meta);
1691 assert(uninitialized || ! sblock.is_initialized());
1693 sblock.attach_internal_block(get_ready_block(schedule_meta));
1696 if (! uninitialized)
1697 sblock.fill_default();
1700 operation_done(schedule_meta);
1701 return sblock.get_internal_block();
1706 assert(! prediction_sequence.empty());
1707 assert(prediction_sequence.front().op ==
1708 ((dirty) ? block_scheduler_type::op_release_dirty : block_scheduler_type::op_release));
1709 assert(prediction_sequence.front().id == sbid);
1710 prediction_sequence.pop_front();
1712 assert(schedule_meta != scheduled_blocks.end());
1713 assert(schedule_meta->second.operations.back() ==
1714 ((dirty) ? block_scheduler_type::op_release_dirty : block_scheduler_type::op_release));
1716 SwappableBlockType& sblock = swappable_blocks[sbid];
1717 sblock.make_dirty_if(dirty);
1719 if (! sblock.is_acquired())
1721 if (sblock.is_dirty() || sblock.is_external())
1724 if (shall_keep_internal_block(schedule_meta))
1727 scheduled_evictable_blocks.insert(sbid);
1728 if (shall_be_cleaned(schedule_meta))
1729 schedule_write(sbid);
1734 free_evictable_blocks.insert(sbid);
1735 if (next_op_to_schedule != prediction_sequence.end())
1736 schedule_next_operations();
1738 if (! write_scheduled_blocks.count(sbid))
1739 schedule_write(sbid);
1746 if (shall_keep_internal_block(schedule_meta))
1748 schedule_meta->second.reserved_iblock = sblock.detach_internal_block();
1752 return_free_internal_block(sblock.detach_internal_block());
1753 if (next_op_to_schedule != prediction_sequence.end())
1754 schedule_next_operations();
1758 operation_done(schedule_meta);
1763 assert(! prediction_sequence.empty());
1764 assert(prediction_sequence.front().op == block_scheduler_type::op_deinitialize);
1765 assert(prediction_sequence.front().id == sbid);
1766 prediction_sequence.pop_front();
1768 assert(schedule_meta != scheduled_blocks.end());
1769 assert(schedule_meta->second.operations.back() == block_scheduler_type::op_deinitialize);
1771 SwappableBlockType& sblock = swappable_blocks[sbid];
1772 if (sblock.is_evictable())
1775 if (shall_keep_internal_block(schedule_meta,
false))
1777 t = scheduled_evictable_blocks.erase(sbid);
1779 STXXL_ERRMSG(
"dirty block not scheduled on deinitialize");
1780 t = free_evictable_blocks.erase(sbid);
1784 t = free_evictable_blocks.erase(sbid);
1789 if (shall_keep_internal_block(schedule_meta))
1791 schedule_meta->second.reserved_iblock = iblock;
1795 return_free_internal_block(iblock);
1796 if (next_op_to_schedule != prediction_sequence.end())
1797 schedule_next_operations();
1800 operation_done(schedule_meta);
1805 assert(! prediction_sequence.empty());
1806 assert(prediction_sequence.front().op == block_scheduler_type::op_initialize);
1807 assert(prediction_sequence.front().id == sbid);
1808 prediction_sequence.pop_front();
1810 assert(schedule_meta != scheduled_blocks.end());
1811 assert(schedule_meta->second.operations.back() == block_scheduler_type::op_initialize);
1813 SwappableBlockType& sblock = swappable_blocks[sbid];
1814 sblock.initialize(eblock);
1815 if (shall_be_read(schedule_meta))
1817 sblock.attach_internal_block(schedule_meta->second.reserved_iblock);
1818 schedule_meta->second.reserved_iblock = 0;
1819 scheduled_evictable_blocks.insert(sbid);
1820 schedule_read(schedule_meta);
1822 operation_done(schedule_meta);
1827 assert(! prediction_sequence.empty());
1828 assert(prediction_sequence.front().op == block_scheduler_type::op_extract_external_block);
1829 assert(prediction_sequence.front().id == sbid);
1830 prediction_sequence.pop_front();
1832 assert(schedule_meta != scheduled_blocks.end());
1833 assert(schedule_meta->second.operations.back() == block_scheduler_type::op_extract_external_block);
1835 SwappableBlockType& sblock = swappable_blocks[sbid];
1836 wait_on_write(sbid);
1837 operation_done(schedule_meta);
1838 return sblock.extract_external_block();
1844 #endif // !STXXL_MNG_BLOCK_SCHEDULER_HEADER
internal_block_type * detach_internal_block()
Detach the internal_block. Writes to external_block if necessary. Has to be evictable.
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...
void wait_on_read(const scheduled_blocks_iterator &schedule_meta)
Wait for the read to finish.
Default completion handler class.
#define STXXL_ASSERT(condition)
block_scheduler_algorithm_type * give_up(std::string err_msg="detected some error in the prediction sequence")
void get_external_block()
bool shall_be_cleaned(const scheduled_blocks_iterator &schedule_meta) const
const int_type max_internal_blocks
block_scheduler_type::internal_block_type internal_block_type
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
void schedule_next_operations()
virtual void swappable_blocks_resize(swappable_block_identifier_type size)
internal_block_type & get_internal_block(const swappable_block_identifier_type sbid) const
Get a const reference to given block's data. Block has to be already acquired.
bool is_initialized(const swappable_block_identifier_type sbid) const
check if the swappable_block is initialized.
void free_swappable_block(const swappable_block_identifier_type sbid)
Free given no longer used temporary swappable_block.
virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock)
virtual bool is_initialized(const swappable_block_identifier_type sbid) const
std::map< swappable_block_identifier_type, write_read_request * > write_scheduled_blocks_type
Completion handler class (Loki-style).
scheduled_blocks_type scheduled_blocks
Holds not internal swappable_blocks, whose next access has already been scheduled.
block_scheduler_operation
scheduled_blocks_type::reference scheduled_blocks_reference
swappable_block_identifier_type id
request_ptr clean_async(completion_handler on_cmpl=default_completion_handler())
Write asyncronusly from internal_block to external_block if necessary.
internal_block_type * get_free_internal_block_from_block_scheduler()
Get an internal_block from the block_scheduler.
void deinitialize(const swappable_block_identifier_type sbid)
Drop all data in the given block, freeing in- and external memory.
swappable_blocks_iterator block_to_start_read
external_block_type external_data
block_scheduler_algorithm< SwappableBlockType > block_scheduler_algorithm_type
block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
virtual void initialize(swappable_block_identifier_type sbid, external_block_type)
SwappableBlockType::internal_block_type internal_block_type
block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
virtual bool is_simulating() const
internal_block_type * get_ready_block(const scheduled_blocks_iterator &schedule_meta)
Wait for the write of the giver to finish and return reserved internal_block.
std::stack< internal_block_type * > internal_blocks_blocks
Stores pointers to arrays of internal_blocks. Used to deallocate them only.
block_scheduler_algorithm< SwappableBlockType > block_scheduler_algorithm_type
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.
block_scheduler_algorithm_offline_lru_prefetching(block_scheduler_algorithm_type *old)
Container::value_type pop_begin(Container &c)
void initialize(const swappable_block_identifier_type sbid, external_block_type eblock)
Initialize the swappable_block with the given external_block.
block_scheduler_algorithm_offline_lfd(block_scheduler_algorithm_type *old)
void read_sync()
Read synchronously from external_block to internal_block. Has to be internal and have an external_blo...
void clean_sync()
Write synchronously from internal_block to external_block if necessary.
An internal priority queue that allows removing elements addressed with (a copy of) themselves...
internal_block_type * get_free_internal_block()
std::vector< SwappableBlockType > swappable_blocks
temporary blocks that will not be needed after algorithm termination.
counting_ptr< request > request_ptr
A reference counting pointer for request.
std::vector< int_type > reference_counts
void init(block_scheduler_algorithm_type *old_algo)
virtual bool is_simulating() const
void explicit_timestep()
Record a timestep in the prediction sequence to seperate consecutive acquire rsp. release-operations...
static uint_pair min()
return an uint_pair instance containing the smallest value possible
virtual bool evictable_blocks_empty()
bool has_external_block() const
If it has an external_block.
scheduled_blocks_type::iterator scheduled_blocks_iterator
virtual ~block_scheduler_algorithm_online_lru()
static const int_type max_internal_blocks_alloc_at_once
virtual const prediction_sequence_type & get_prediction_sequence() const
block_scheduler_algorithm_online_lru(block_scheduler_algorithm_type *old)
internal_block_type * internal_data
external_data.valid if no associated space on disk
prediction_sequence_type prediction_sequence
block_scheduler_algorithm_offline_lfd(block_scheduler_type &bs)
block_scheduler_type::time_type time_type
block_scheduler_type::prediction_sequence_type prediction_sequence_type
Virtualization of a block of data. Holds information for allocating and swapping. To use in cooperati...
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)
bool valid() const
test for a non-NULL pointer
bool is_simulating() const
Returns if simulation mode is on, i.e. if a prediction sequence is being recorded.
block_scheduler< SwappableBlockType > block_scheduler_type
std::stack< swappable_block_identifier_type > evictable_blocks
Holds swappable blocks, whose internal block can be freed, i.e. that are internal but unacquired...
Block scheduling algorithm caching via the least recently used policy (offline), and prefetching in a...
internal_block_type::bid_type external_block_type
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
prediction_sequence_type::iterator next_op_to_schedule
void return_free_internal_block(internal_block_type *iblock)
block_scheduler< SwappableBlockType > block_scheduler_type
internal_block_type * deinitialize()
Bring the block in uninitialized state, freeing external and internal memory. Returns a pointer to th...
void initialize(external_block_type eblock)
Set the external_block that holds the swappable_block's data. The block gets initialized with it...
void free_external_block()
Block scheduling algorithm caching via the least recently used policy (online).
virtual void deinitialize(swappable_block_identifier_type sbid)
request_ptr read_async(completion_handler on_cmpl=default_completion_handler())
Read asyncronusly from external_block to internal_block. Has to be internal and have an external_bloc...
write_scheduled_blocks_type::iterator write_scheduled_blocks_iterator
void init(block_scheduler_algorithm_type *old_algo)
block_scheduler_algorithm * get_algorithm_from_block_scheduler()
block_scheduler_type::external_block_type external_block_type
SwappableBlockType::external_block_type external_block_type
bool is_initialized() const
If it has some valid data (in- or external).
block_scheduler_algorithm_type::time_type time_type
virtual ~block_scheduler_algorithm_simulation()
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
block_scheduler_type::prediction_sequence_type prediction_sequence_type
Block containing elements of fixed length.
virtual void wait(bool measure_time=true)=0
Suspends calling thread until completion of the request.
scheduled_blocks_iterator taker
virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock)
block_scheduler_type::external_block_type external_block_type
internal_block_type & acquire()
Acquire the block, i.e. add a reference. Has to be internal.
virtual ~block_scheduler_algorithm()
void operation_done(scheduled_blocks_iterator &schedule_meta)
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
block_scheduler_algorithm_simulation(block_scheduler_algorithm_type *old)
virtual bool is_initialized(const swappable_block_identifier_type sbid) const
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)
choose_int_types< my_pointer_size >::int_type int_type
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.
bool try_interrupt_read(const write_scheduled_blocks_iterator &writing_block)
Try to interrupt a read scheduled in a write_read_request.
bool shall_be_read(const scheduled_blocks_iterator &schedule_meta, const bool ignore_first=true) const
block_scheduler_type::external_block_type external_block_type
virtual void initialize(swappable_block_identifier_type sbid, external_block_type eblock)
internal_block_type * get_free_internal_block()
Get an internal_block from the freelist or a newly allocated one if available.
block_scheduler< SwappableBlockType > block_scheduler_type
virtual void deinitialize(swappable_block_identifier_type sbid)
bool is_acquired() const
If it is acquired.
int_type remaining_internal_blocks
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...
virtual bool evictable_blocks_empty()
Striping disk allocation scheme functor.
swappable_block_identifier_type allocate_swappable_block()
Allocate an uninitialized swappable_block.
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...
void wait_on_write(const write_scheduled_blocks_iterator &writing_block)
Wait for the write to finish.
block_scheduler_type::external_block_type external_block_type
Pseudo block scheduling algorithm only recording the request sequence.
bool operator<(const uint_pair &b) const
less-than comparison operator
block_scheduler_algorithm_simulation(block_scheduler_type &bs)
block_scheduler_operation op
#define STXXL_BEGIN_NAMESPACE
write_scheduled_blocks_type::reference write_scheduled_blocks_reference
std::vector< SwappableBlockType >::size_type swappable_block_identifier_type
const internal_block_type & get_internal_block() const
Get a reference to the data-block. Has to be acquired.
read_after_write(write_read_request *write_read_req)
block_scheduler(const int_type max_internal_memory)
Create a block_scheduler with empty prediction sequence in simple mode.
block_scheduler_type::block_scheduler_operation block_scheduler_operation
write_read_request * schedule_write(const swappable_block_identifier_type sbid)
Schedule an internal, possibly dirty swappable_block to write.
virtual ~block_scheduler_algorithm_offline_lru_prefetching()
std::map< swappable_block_identifier_type, scheduled_block_meta > scheduled_blocks_type
block_scheduler_algorithm(block_scheduler_algorithm *old)
bool shall_keep_internal_block(const scheduled_blocks_iterator &schedule_meta, const bool ignore_first=true) const
virtual void deinitialize(swappable_block_identifier_type sbid)
virtual swappable_block_identifier_type evictable_blocks_pop()
const prediction_sequence_type & get_prediction_sequence() const
Get the prediction_sequence.
std::list< prediction_sequence_element > prediction_sequence_type
static uint_pair max()
return an uint_pair instance containing the largest value possible
virtual swappable_block_identifier_type evictable_blocks_pop()
internal_block_type dummy_block
void return_free_internal_block_to_block_scheduler(internal_block_type *iblock)
Return an internal_block to the block_scheduler.
block_scheduler_type::prediction_sequence_type prediction_sequence_type
virtual swappable_block_identifier_type evictable_blocks_pop()
typed_block< raw_block_size, ValueType > internal_block_type
block_scheduler_type::internal_block_type internal_block_type
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
virtual void swappable_blocks_resize(swappable_block_identifier_type)
void fill_default()
Fill block with default data, is supposed to be overwritten by subclass. Has to be internal...
virtual internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
void schedule_read(scheduled_blocks_iterator block_to_read)
Schedule an internal and external block to read.
virtual void deinitialize(swappable_block_identifier_type sbid)
virtual void explicit_timestep()
virtual void release(swappable_block_identifier_type sbid, const bool dirty)=0
bool is_dirty() const
If the external_block does not hold valid data.
swappable_block()
Create in uninitialized state.
block_scheduler_type::internal_block_type internal_block_type
Block scheduling algorithm caching via the longest forward distance policy (offline).
block_scheduler_algorithm_online_lru(block_scheduler_type &bs)
void attach_internal_block(internal_block_type *iblock)
Attach an internal_block, making the block internal. Has to be not internal.
block_scheduler_algorithm< SwappableBlockType > * algo
std::set< swappable_block_identifier_type > scheduled_evictable_blocks
std::vector< SwappableBlockType >::iterator swappable_blocks_iterator
block_scheduler< SwappableBlockType > block_scheduler_type
void wait_on_write(const swappable_block_identifier_type &writing_block)
Wait for the write to finish.
block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
bool is_external() const
If it has an external_block that holds valid data.
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
virtual bool evictable_blocks_empty()
priority(const SwappableBlockType &sblock, const std::pair< bool, time_type > &t)
block_scheduler_algorithm(block_scheduler_type &bs)
internal_block_type * get_free_internal_block()
compat::remove_const< Integral >::type div_ceil(Integral __n, Integral2 __d)
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)
static unsigned_type disk_allocation_offset
std::vector< SwappableBlockType > & swappable_blocks
void return_free_internal_block(internal_block_type *iblock)
block_scheduler_type::internal_block_type internal_block_type
block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
void release()
Release the block, i.e. subduct a reference. Has to be acquired.
void return_free_internal_block(internal_block_type *iblock)
Return an internal_block to the freelist.
prediction_sequence_element(block_scheduler_operation op, swappable_block_identifier_type id, int_type time)
void release(const swappable_block_identifier_type sbid, const bool dirty)
Release the given block. Has to be in pairs with acquire. Pairs may be nested and interleaved...
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
virtual external_block_type extract_external_block(swappable_block_identifier_type sbid)
Schedules swapping of blocks and provides blocks for temporary storage.
block_scheduler_algorithm_type::time_type time_type
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_type::internal_block_type internal_block_type
void return_free_internal_block(internal_block_type *iblock)
block_scheduler_algorithm< SwappableBlockType > * get_current_algorithm() const
Return the current algorithm.
block_scheduler_type::swappable_block_identifier_type swappable_block_identifier_type
block_scheduler_type::prediction_sequence_element prediction_sequence_element_type
block_scheduler_algorithm_offline_lru_prefetching(block_scheduler_type &bs)
virtual swappable_block_identifier_type evictable_blocks_pop()
block_scheduler< SwappableBlockType > block_scheduler_type
virtual void release(swappable_block_identifier_type sbid, const bool dirty)
bool make_dirty_if(const bool make_dirty)
Invalidate external data if true.
Interface of a block scheduling algorithm.
block_scheduler_algorithm< SwappableBlockType > block_scheduler_algorithm_type
external_block_type extract_external_block()
Extract the swappable_blocks data in an external_block. The block gets uninitialized.
block_scheduler_algorithm< SwappableBlockType > * switch_algorithm_to(block_scheduler_algorithm< SwappableBlockType > *new_algo)
Switch the used algorithm, e.g. to simulation etc..
virtual ~block_scheduler_algorithm_offline_lfd()
Request with basic properties like file and offset.
virtual void explicit_timestep()
virtual bool evictable_blocks_empty()
block_scheduler_algorithm_type::time_type time_type
block_scheduler_type & bs
std::stack< internal_block_type * > free_internal_blocks
holds free internal_blocks with attributes reset.
bool is_internal() const
If it has an internal_block. The internal_block implicitly holds valid data.
block_scheduler_type::external_block_type external_block_type
block_scheduler_algorithm< SwappableBlockType > block_scheduler_algorithm_type
void wait_on_write(const scheduled_blocks_iterator &schedule_meta)
Wait for the write of the giver to finish.
void return_free_internal_block(internal_block_type *iblock)
#define STXXL_END_NAMESPACE
internal_block_type & get_internal_block()
Get a reference to the data-block. Has to be acquired.
internal_block_type & acquire(const swappable_block_identifier_type sbid, const bool uninitialized=false)
Acquire the given block. Has to be in pairs with release. Pairs may be nested and interleaved...
external_block_type extract_external_block(const swappable_block_identifier_type sbid)
Deinitialize the swappable_block and return it's contents in an external_block.
bool is_evictable() const
If it holds an internal_block but does not need it.